[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/csharp-mode 2a28871 026/459: clean out unused files
From: |
ELPA Syncer |
Subject: |
[elpa] externals/csharp-mode 2a28871 026/459: clean out unused files |
Date: |
Sun, 22 Aug 2021 13:58:48 -0400 (EDT) |
branch: externals/csharp-mode
commit 2a2887135ea3cacc2afe8969019a3adacf0b7512
Author: Jesse Black <jesse.w.black@gmail.com>
Commit: Jesse Black <jesse.w.black@gmail.com>
clean out unused files
---
CscompUtilities.cs | 2639 ----------------------------------------
CscompUtilities.dll | Bin 57344 -> 0 bytes
ICSharpCode.NRefactory.dll | Bin 606208 -> 0 bytes
aspx-mode.el | 496 --------
cscomp-base.el | 35 -
csharp-analysis.el | 1533 -----------------------
csharp-completion.el | 2902 --------------------------------------------
csharp-shell.el | 417 -------
tfs.el | 554 ---------
9 files changed, 8576 deletions(-)
diff --git a/CscompUtilities.cs b/CscompUtilities.cs
deleted file mode 100644
index b24005e..0000000
--- a/CscompUtilities.cs
+++ /dev/null
@@ -1,2639 +0,0 @@
-// CscompUtilities.cs
-// ------------------------------------------------------------------
-//
-// Author: Dinoch
-// built on host: DINOCH-2
-// Created Mon Apr 21 08:40:47 2008
-//
-// Last Saved: <2011-May-12 15:19:19>
-//
-//
-// This file defines code for an assembly containing one main class, a
-// static class that exposes only static methods. The assembly is
-// intended to run within Powershell, in an emacs inferior shell.
-//
-// Using csharp-complete.el, when the user asks for code-completion on a
-// segment of code, csharp-complete will send a command in the
-// powershell - which just invokes a method on this static
-// class.
-//
-// The logic in this assembly will then perform whatever is necessary:
-// reflect on the specified type, or qualify a name, and so on, and then
-// return the result information to the Csharp Completion elisp logic.
-//
-// In broad strokes, you can think of this assembly as the thing that
-// performs .NET reflection, and sends the list of potential completions
-// to elisp, which presents a pop-up menu. There are a bunch of
-// supplementary tasks required, in order to make the "return the list
-// of potential completions" possible: for example, is the completion
-// being requested on a type? A namespace? is it a static method? A
-// property? and so on. All of these extra supporting functions are also
-// implemented as static methods on the main Utilities class.
-//
-// =======================================================
-//
-// compile with:
-// csc.exe /target:library /debug /out:CscompUtilities.dll
CscompUtilities.cs
-//
-// ------------------------------------------------------------------
-//
-// Copyright (c) 2008-2011 by Dino Chiesa
-// All rights reserved!
-//
-// ------------------------------------------------------------------
-
-
-
-
-using System;
-using System.IO;
-using System.Linq;
-using System.Diagnostics;
-using System.Collections.Generic;
-using System.Text;
-using System.Text.RegularExpressions;
-using System.Reflection;
-using ICSharpCode.NRefactory;
-using ICSharpCode.NRefactory.Ast;
-
-// to allow fast ngen
-[assembly: AssemblyTitle("CscompUtilities.cs")]
-[assembly: AssemblyDescription("an assembly to be loaded into powershell,
allows integration with emacs, code completion, etc.")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("Dino Chiesa")]
-[assembly: AssemblyProduct("Tools")]
-[assembly: AssemblyCopyright("Copyright � Dino Chiesa 2010, 2011")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-[assembly: AssemblyVersion("1.3.0.2")]
-
-
-namespace Ionic.Cscomp
-{
- public static class Utilities
- {
- private static List<string> StarterAssemblies = new List<string>()
- {
- "System, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089",
- "mscorlib, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089"
- // {"System.Xml","Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089" },
- // {"System.Xml.Linq", "Version=3.5.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089" },
- // {"System.Data", "Version=3.5.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089" },
- };
-
-
- // "Microsoft.JScript",
- // "Microsoft.VisualBasic",
- // "Microsoft.VisualBasic.Vsa",
- // "Microsoft.VisualC",
- // "Microsoft.Vsa",
- // "Microsoft.Vsa.Vb.CodeDOMPRocessor",
- // "System.Configuration.Install",
- // "System.Data",
- // "System.Design",
- // "System.DirectoryServices",
- // "System.Drawing",
- // "System.Drawing.Design",
- // "System.EnterpriseServices",
- // "System.Management",
- // "System.Messaging",
- // "System.Runtime.Remoting",
- // "System.Runtime.Serialization.Formatters.Soap",
- // "System.Security",
- // "System.ServiceProcess",
- // "System.Web",
- // "System.Web.RegularExpressions",
- // "System.Web.Services",
- // "System.Windows.Forms",
-
- private static List<String> _GacAssemblies;
- private static Dictionary<String,Object> _assembliesNotLoaded;
- private static Dictionary<String,Assembly> _assembliesLoaded;
- private static Dictionary<String,String> _assemblyForType;
- private static Dictionary<String,List<String>> _typesForNamespace;
- private static Dictionary<String,String> _fullNamesForShortNames;
- private static List<String> _SearchPaths;
-
- static Utilities()
- {
- try
- {
- SetBasicSearchPaths();
- ReadGac(false);
- LoadAssembliesAndPopulateHashes();
- }
- catch (System.Exception exc1)
- {
- System.Console.WriteLine("uncaught exception {0}", exc1);
- }
- }
-
- public static string ReadGac(bool wantList)
- {
- if (_GacAssemblies == null)
- {
- var p = new System.Diagnostics.Process
- {
- StartInfo =
- {
- FileName = "gacutil.exe",
- CreateNoWindow = true,
- Arguments = "-l",
- RedirectStandardOutput = true,
- //RedirectStandardError = true,
- WindowStyle =
System.Diagnostics.ProcessWindowStyle.Hidden,
- UseShellExecute = false,
- }
- };
-
- p.Start();
- _GacAssemblies = new List<String>();
-
- string output = p.StandardOutput.ReadToEnd();
- string[] lines = output.Split("\n".ToCharArray());
- foreach (var line in lines)
- {
- var mcol= Regex.Matches(line,"^([^,]+), *(.+)");
- foreach (Match match in mcol)
- {
- // var p1 = match.Groups[1].Value;
- // var p2 = match.Groups[2].Value;
- // System.Console.WriteLine("{0}, {1}", p1, p2);
- _GacAssemblies.Add(line.Trim());
- }
- }
-
- }
-
- if (!wantList) return "t";
-
- string atoms = String.Join("\" \"", _GacAssemblies.ToArray());
- return "(list \"" + atoms + "\")";
- }
-
-
- // private static string ExpandEnvVarsInPath(string path)
- // {
- // bool done;
- // do
- // {
- // done= true;
- // Match match = Regex.Match(path,"%([^%]+)%");
- // if (match.Success)
- // {
- // done= false;
- // var envvar = match.Groups[1].Value.ToString();
- // var value =
System.Environment.GetEnvironmentVariable(envvar);
- // path = path.Replace("%"+envvar+"%", value);
- // }
- // } while (!done);
- // return path;
- // }
-
-
-
- private static void SetBasicSearchPaths()
- {
- _SearchPaths= new List<String>();
-
- Microsoft.Win32.RegistryKey rkey=
- Microsoft.Win32.Registry.LocalMachine.OpenSubKey
- ("SOFTWARE\\Microsoft\\.NETFramework", false);
-
- String DotNetDir= (string) rkey.GetValue("InstallRoot");
- string programFiles =
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
-
- foreach (var path in new String[] {
- Path.Combine(DotNetDir,"v2.0.50727"),
-
- Path.Combine(programFiles,"Reference
Assemblies\\Microsoft\\Framework\\v3.5"),
- Path.Combine(programFiles,"Reference
Assemblies\\Microsoft\\Framework\\v3.0") } )
- {
- if (Directory.Exists(path))
- {
- Tracing.Trace("SetBasicSearchPaths: {0}", path);
- _SearchPaths.Add(path);
- }
- }
- }
-
-
- // private static Assembly LoadRefAssembly(string fileName)
- // {
- // var fullPath = FindAssemblyInSearchPaths(fileName);
- // if (fullPath != null)
- // return Assembly.LoadFrom(fullPath) ;
- // }
-
-
-
-
- private static Assembly AssemblyIsLoaded(string assemblyName)
- {
- // exact match
- if (_assembliesLoaded.Keys.Contains(assemblyName))
- return _assembliesLoaded[assemblyName];
-
- // check for short name
- if (!assemblyName.Contains(","))
- {
- foreach (var key in _assembliesLoaded.Keys)
- {
- int ix = key.LastIndexOf(',');
- if (ix > 0)
- {
- var stub = key.Substring(0, ix);
- if (assemblyName == stub)
- return _assembliesLoaded[key];
- }
- }
- }
- return null;
- }
-
-
-
- private static String InternalLoadOneAssembly(string assemblyName)
- {
- // assemblyName can be a path, or a fully-qualified name, or
- // a partially qualified name. We need to map all those to
- // the FQ name.
- Tracing.Trace("InternalLoadOneAssembly '{0}'", assemblyName);
-
- if (String.IsNullOrEmpty(assemblyName))
- {
- Tracing.Trace("InternalLoadOneAssembly: arg is null, returning
null");
- return null;
- }
-
- // check if already loaeded
- if (AssemblyIsLoaded(assemblyName)!=null)
- {
- Tracing.Trace("InternalLoadOneAssembly: already loaded");
- return "t";
- }
-
- // maybe not already loaded. Try to load it.
- Assembly thisAssembly = null;
- try
- {
- thisAssembly = TryLoadAssembly(assemblyName);
- }
- catch(Exception exc1)
- {
- _assembliesNotLoaded[assemblyName] = exc1;
- Tracing.Trace("InternalLoadOneAssembly: exception: {0}", exc1);
- return null;
- }
-
- if (thisAssembly == null)
- {
- _assembliesNotLoaded[assemblyName] = "Assembly was null.";
- Tracing.Trace("InternalLoadOneAssembly: loaded assembly was
null");
- return null;
- }
-
- // ok, we now have an assembly loaded
- string shortName = thisAssembly.FullName.Split(',')[0];
-
- // check if already loaeded
- if (AssemblyIsLoaded(shortName)!=null)
- {
- Tracing.Trace("InternalLoadOneAssembly: assembly '{0}' already
loaded",
- shortName);
- return "t";
- }
-
- Tracing.Trace("InternalLoadOneAssembly: loading assembly '{0}'...",
- thisAssembly.FullName);
- _assembliesLoaded.Add(shortName, thisAssembly);
-
- Module[] ma = thisAssembly.GetModules();
- if (ma != null)
- {
- List<String> list;
-
- for (int k = 0; k < ma.Length; k++)
- {
- try
- {
- if (ma[k] == null) continue;
-
- Type[] types = ma[k].GetTypes();
- if (types == null) continue;
-
- foreach (Type t in types)
- {
- try
- {
- if (t == null) continue;
- String ns = t.Namespace;
- if (ns == null) ns = String.Empty;
-
- if (_typesForNamespace.ContainsKey(ns))
- list= (List<String>)
_typesForNamespace[ns];
- else
- {
- list= new List<String>();
- _typesForNamespace[ns]= list;
- }
-
- // sometimes we get duplicate types
- if (!list.Contains(t.FullName))
- {
- list.Add(t.FullName);
- //_assemblyForType[t.FullName]=
assemblyName;
- _assemblyForType[t.FullName]= shortName;
- var fixedName =
FixupGenericTypeName(t.Name);
- if
(_fullNamesForShortNames.ContainsKey(fixedName))
- {
- var x =
_fullNamesForShortNames[fixedName];
- _fullNamesForShortNames[fixedName] =
- String.Format("{0}, {1}",
t.FullName, x);
- }
- else
- _fullNamesForShortNames[fixedName] =
t.FullName;
- }
- }
- catch(ReflectionTypeLoadException)
- {
- //Response.Write("Problem with : " +
t.FullName);
- continue;
- }
- }
- }
- catch(Exception)
- {
- continue;
- }
- }
- }
-
- return shortName; // assemblyName
- }
-
-
- private static void LoadAssembliesAndPopulateHashes()
- {
- _assembliesNotLoaded = new Dictionary<String,Object>();
- _assemblyForType = new Dictionary<String,String>();
- _typesForNamespace = new Dictionary<String,List<String>>();
- _fullNamesForShortNames = new Dictionary<String,String>();
- _assembliesLoaded = new Dictionary<String,Assembly>();
-
- foreach (var aname in StarterAssemblies)
- {
- InternalLoadOneAssembly(aname);
- }
-
- Alphabetize();
- }
-
-
- private static void Alphabetize()
- {
- foreach (string key in _typesForNamespace.Keys)
- {
- _typesForNamespace[key].Sort();
- }
- }
-
-
- public static String GetTypeInfo(String typeName)
- {
- string q= null;
- String[] s = null;
- try
- {
- q= QualifyType(typeName);
- s = q.Replace(")","").Replace("(","").Split(" ".ToCharArray(),
3);
- return GetTypeInfo(s[1].Replace("\"",""),
s[2].Replace("\"",""));
-
- }
- catch (System.Exception exc1)
- {
- System.Console.WriteLine("uncaught exception {0}",
exc1.ToString());
- System.Console.WriteLine("q= {0}", q);
- System.Console.WriteLine("s.Length= {0}", s.Length);
- throw ;
- }
- }
-
-
- public static String GetTypeInfo(String typeName, String assemblyName)
- {
- try
- {
- if (_assemblyForType.Keys.Contains(typeName) &&
- _assemblyForType[typeName] == assemblyName &&
- _assembliesLoaded.Keys.Contains(assemblyName))
- {
- Assembly a2 = _assembliesLoaded[assemblyName];
- Ionic.Cscomp.TypeInfo ti2= new Ionic.Cscomp.TypeInfo(a2,
typeName);
- return ti2.AsSexp();
- }
-
- // Load from a strongname, eg
- // "System.Windows.Forms, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089"
-
- Assembly a= Assembly.Load(assemblyName);
-
- if ((a == null) && (System.IO.File.Exists(assemblyName)))
- a= Assembly.LoadFrom(assemblyName);
-
- if (a == null)
- {
- System.Console.Error.WriteLine("Cannot load that
assembly");
- return null;
- }
-
- Ionic.Cscomp.TypeInfo ti= new Ionic.Cscomp.TypeInfo(a,
typeName);
- return ti.AsSexp();
- }
- catch(TypeLoadException e2)
- {
- Console.Error.WriteLine("TypeLoadException: Could not load
type: \"{0}\"\n{1}", typeName, e2);
-
- return null;
- }
- catch (Exception e1)
- {
- Console.Error.WriteLine("Exception: type '{0}'\n{1}",
typeName, e1);
- return null;
- }
- }
-
-
-
- private static Assembly TryLoadAssembly(String assemblyName)
- {
- Assembly a= null;
-
- if (assemblyName.Contains(','))
- {
- // smells like a fully-qualified name
- Tracing.Trace("TryLoadAssembly: loading as strong name");
- a= Assembly.Load(assemblyName);
- }
- else if (assemblyName.EndsWith(".dll") ||
assemblyName.EndsWith(".exe"))
- {
- Tracing.Trace("TryLoadAssembly: looks like a filename");
- if (System.IO.File.Exists(assemblyName))
- {
- Tracing.Trace("TryLoadAssembly: file exists");
- a= Assembly.LoadFrom(assemblyName) ;
- }
- else
- {
- // look in search paths
- var fullname = FindAssemblyInSearchPaths(assemblyName);
- if (fullname != null && fullname != "nil")
- {
- a= Assembly.LoadFrom(fullname.Replace("\"", ""));
- }
- }
- }
- else
- {
- var dll = GetShortDllName(assemblyName);
- var fullname = FindAssemblyInSearchPaths(dll);
- if (fullname != null && fullname != "nil")
- {
- fullname = fullname.Replace("\"", "");
- Tracing.Trace("TryLoadAssembly: LoadFrom({0})", fullname);
- a= Assembly.LoadFrom(fullname);
- }
- }
-
- return a; // maybe null
- }
-
-
-
- private static System.Type TryLoadType(String theTypeName, String
assemblyName)
- {
- System.Type t= null;
- Assembly a= TryLoadAssembly(assemblyName);
- if (a != null)
- t = a.GetType(theTypeName, false, true);
- return t; // maybe null
- }
-
-
- public static String LoadOneAssembly (string name)
- {
- Tracing.Trace("LoadOneAssembly: {0}", name);
- try
- {
- string r = InternalLoadOneAssembly(name);
-
- if (r == null)
- {
- Tracing.Trace("LoadOneAssembly: null");
- return "nil";
- }
-
- Alphabetize();
-
- if (r == "t") {
- Tracing.Trace("LoadOneAssembly: already loaded.");
- return r;
- }
-
- var retval = "\"" + r + "\"";
- // need this? Don't think so.
- // Only if the return value is a path.
- retval = retval.Replace("\\", "\\\\");
- Tracing.Trace("returning: [{0}]", retval);
- return retval;
- }
- catch (System.Exception exc1)
- {
- Tracing.Trace("uncaught exception: {0} {1}", exc1,
exc1.StackTrace);
- throw;
- }
- }
-
-
-
- public static String ListLoadedAssemblies ()
- {
- string atoms = String.Join("\" \"",
_assembliesLoaded.Keys.ToArray());
- return "(list \"" + atoms + "\")";
- }
-
-
- /// <summary>
- /// Gets the version of the assembly, in a string form.
- /// </summary>
- /// <remarks>
- /// <para>
- /// Returns a quoted string, suitable for use as a lisp
- /// s-expression. Example: "1.2.0.4"
- /// </para>
- /// </remarks>
- /// <returns>
- /// The quoted version string
- /// </returns>
- public static String Version ()
- {
- return "\"" +
-
System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString()
+ "\"";
- }
-
-
- public static String ListKnownTypes()
- {
- string atoms = String.Join("\" \"",
_assemblyForType.Keys.ToArray());
- return "(list \"" + atoms + "\")" ;
- }
-
-
-
- /// <summary>
- /// Gets all the known completions in the given namespace.
- /// </summary>
- /// <remarks>
- /// <para>
- /// The completions include all the types, and all the child
namespaces.
- /// So, for ns "System", the completion list will include
System.Delegate
- /// as well as System.Diagnostics
- /// </para>
- /// </remarks>
- /// <returns>
- /// </returns>
- public static String GetCompletionsForNamespace(string ns)
- {
- if (String.IsNullOrEmpty(ns))
- {
- Tracing.Trace("GetCompletionsForNamespace: null input");
- return null;
- }
-
- if (!_typesForNamespace.ContainsKey(ns))
- {
- Tracing.Trace("GetCompletionsForNamespace: unknown ns '{0}'",
ns);
- return null;
- }
-
- var result= new System.Text.StringBuilder();
- int len = ns.Length+1;
- result.Append("(list \"").Append(ns).Append("\" (list 'types (list
");
- foreach (var t in _typesForNamespace[ns])
- {
- var s = t.Substring(len);
- //System.Console.WriteLine(" " + t.Substring(len));
- //Tracing.Trace(" {0}", s);
- result.Append("\"").Append(s).Append("\" ");
- }
- result.Append("))");
-
- var childlist = new List<String>();
- foreach (var key in _typesForNamespace.Keys)
- {
- if (key.StartsWith(ns) && !key.Equals(ns))
- {
- var child = key.Substring(len);
- var p = child.IndexOf('.');
- if (p > 0)
- child = child.Substring(0,p);
- if (!childlist.Contains(child))
- childlist.Add(child);
- }
- }
-
- if (childlist.Count() > 0)
- {
- result.Append(" (list 'namespaces (list ");
- foreach (var c in childlist)
- result.Append("\"").Append(c).Append("\" ");
- result.Append("))");
- }
-
- result.Append(")");
- return result.ToString();
- }
-
-
- private static string Escape(string s)
- {
- return s.Replace("\"", "\\\"");
- }
-
-
- /// <summary>
- /// Qualify a name
- /// </summary>
- /// <returns>
- /// ("type" fulltypename) if the name is a type
- /// ("namespace" parentNamespace) if the name is a namespace
- /// ("unknown" name) if the name is a namespace
- /// </returns>
- public static String QualifyName(String name)
- {
- Tracing.Trace("QualifyName ({0})", name);
-
- var suffix = "." + name;
- IEnumerable<String> collection;
-
- // if (!name.Contains("."))
- // {
- // // no dot in the name = assume short name
- // collection = _fullNamesForShortNames.Keys;
- //
- // // check for exact match in the keys
- // foreach (var key in collection)
- // {
- // if (key.Equals(name))
- // return String.Format("(list \"type\"
\"{0}\")",
- //
_fullNamesForShortNames[key]);
- // }
- //
- // return String.Format("(list \"unknown\"
\"{0}\")",name);
- // }
-
- if (Verbose)
- System.Console.WriteLine("checking name: {0}", name);
-
- // look for exact match on a fully-qualified typename
- collection = _fullNamesForShortNames.Values;
- foreach (var value in collection)
- {
- foreach (var v2 in value.Split(", ".ToCharArray()))
- {
- if (v2.Equals(name))
- return String.Format("(list \"type\" \"{0}\")", v2);
- }
- }
-
- // look for ends-with match on a fully-qualified typename
- foreach (var value in collection)
- {
- foreach (var v2 in value.Split(", ".ToCharArray()))
- {
- if (v2.EndsWith(suffix))
- return String.Format("(list \"type\" \"{0}\")", v2);
- }
- }
-
- // now check for exact match on known namespaces...
- collection = _typesForNamespace.Keys;
- foreach (var key in collection)
- {
- if (key.Equals(name))
- return String.Format("(list \"namespace\" \"{0}\")", name);
- }
-
- // Match on the last segment of the namespace. Eg, if name is
"Diagnostics",
- // should match on "System.Diagnostics".
- foreach (var key in collection)
- {
- if (key.EndsWith(suffix))
- return String.Format("(list \"namespace\" \"{0}\")", key);
- }
-
- Tracing.Trace("checking GAC...");
- // Finally, check the names of assemblies in the gac.
- // If found, load the assembly.
- collection = _GacAssemblies;
- foreach (var strongname in collection)
- {
- var parts = strongname.Split(", ".ToCharArray());
- if (parts!= null && parts[0].Equals(name))
- {
- var r = LoadOneAssembly(strongname);
- if (r!=null && r != "nil")
- return String.Format("(list \"namespace\" \"{0}\")",
name);
- }
- }
-
- return String.Format("(list \"unknown\" \"{0}\")", Escape(name));
- }
-
-
-
- /// <summary>
- /// Return all possible matches on a given symbol fragment.
- /// </summary>
- ///
- /// <param name='fragment'>
- /// the fragment of the name to match on.
- /// </param>
- ///
- /// <param name='namespaces'>
- /// a comma-separated list of namespaces
- /// </param>
- ///
- /// <returns>
- /// a list containing pairs of all possible completions.
- /// eg, if completing on Ba?, maybe return:
- /// (list
- /// ("type" "Foo.Bar")
- /// ("type" "Utils.Bands")
- /// ("namespace" "Barrels")
- /// )
- /// </returns>
- public static String GetMatches(String fragment, String namespaces)
- {
- if (String.IsNullOrEmpty(fragment))
- return "nil";
-
- List<String> responseSet = new List<String>();
- var reTypeStub = "\\." + fragment + ".*$";
- var reNamespace = "^" + fragment + ".*$";
- IEnumerable<String> collection;
- Tracing.Trace("checking fragment: {0}", fragment);
-
- // look for types with short names that begin with the fragment
- collection = _fullNamesForShortNames.Values;
- foreach (string ns in namespaces.Split(','))
- {
- foreach (var value in collection)
- {
- foreach (var v2 in value.Split(", ".ToCharArray()))
- {
- Match match = Regex.Match(v2,"^"+ns+reTypeStub);
- if (match.Success)
- responseSet.Add(String.Format("(list \"type\"
\"{0}\")", v2));
- }
- }
- }
-
- // look for namespaces that begin with the fragment
- collection = _typesForNamespace.Keys;
- foreach (var key in collection)
- {
- Match match = Regex.Match(key,reNamespace);
- if (match.Success)
- responseSet.Add(String.Format("(list \"namespace\"
\"{0}\")", key));
-
- // I think maybe we want to exclude child namespaces. . .
- // maybe later.
- }
-
- if (responseSet.Count == 0)
- return "nil";
-
- string items = String.Join(" ", responseSet.ToArray());
- return "(list " + items + ")";
- }
-
-
- public static string FixupGenericTypeName(string typeName)
- {
- var name = typeName;
- Match match = Regex.Match(name,"(.+)`([1-9])$");
- if (match.Success)
- name = match.Groups[1].Value.ToString();
- return name;
- }
-
-
- public static String QualifyType(String typeName)
- {
- return QualifyType(typeName, null);
- }
-
-
- /// <summary>
- /// Qualifies the type name.
- /// </summary>
- /// <param name='typeName'>
- /// the name of the type, possibly a short name, like "Console" or
"Stream",
- /// and possibly a long name like System.IO.Stream
- /// </param>
- /// <param name='usinglist'>
- /// a list of namespaces referenced at the top of the module in using
- /// statements. Favor these namespaces when doing type qualification.
- /// </param>
- /// <returns>
- /// sexp: (list "fulltypename" "assemblyname") or nil if the type
is not known
- /// The assembly name
- /// </returns>
- public static String QualifyType(String typeName, String usinglist)
- {
- string stub = null;
- System.Text.StringBuilder residual = null;
- int repeats = 0;
-
- Tracing.Trace("QualifyType: {0}", typeName);
-
- // fixup generic type
- var name = typeName;
- Match match = Regex.Match(name,"(.+`[1-9])\\[.+\\]$");
- if (match.Success)
- name = match.Groups[1].Value.ToString();
-
- name = name.Trim();
- Tracing.Trace("QualifyType: name '{0}'", name);
-
- if (!name.Contains("."))
- {
- Tracing.Trace("QualifyType: name contains no dot");
- Tracing.Trace("QualifyType: examining {0} short names",
- _fullNamesForShortNames.Keys.Count);
-
- foreach (var key in _fullNamesForShortNames.Keys)
- {
- var value = _fullNamesForShortNames[key];
-
- if (key.Equals(name))
- {
- string tname = null;
- if (_fullNamesForShortNames[key].Contains(','))
- {
- var nlist = _fullNamesForShortNames[key].Split(",
".ToCharArray());
- if (usinglist != null)
- {
- var ulist = usinglist.Split(",
".ToCharArray());
-
- var GetNamespace = new Func<string,string>((s)
=>
- {
- int ix = s.LastIndexOf('.') ;
- if (ix <= 0)
- return null;
- return s.Substring(0,ix);
- });
-
- var selection = from fn in nlist
- join u in ulist on GetNamespace(fn) equals
u
- select fn;
-
- int c = selection.Count();
-
- tname = (c>=1)
- ? selection.First()
- : nlist[0];
- }
- else
- tname = nlist[0];
- }
- else
- {
- tname = _fullNamesForShortNames[key];
- }
-
- return
- String.Format("(list \"{0}\" \"{1}\")",
- tname,
- _assemblyForType[tname]);
- }
- }
- }
-
- // it may be a fully- or partially qualified type name
- Tracing.Trace("QualifyType: examining {0} full names",
- _fullNamesForShortNames.Values.Count);
-
- foreach (var v1 in _fullNamesForShortNames.Values)
- {
- foreach (var value in v1.Split(", ".ToCharArray()))
- {
- if (stub == null || !value.StartsWith(stub))
- {
- int ix = value.LastIndexOf('.');
- stub= (ix > 0)
- ? value.Substring(0, ix)
- : value ;
- repeats = 0;
- if (residual!=null)
- {
- var r = residual.ToString();
- if (!String.IsNullOrEmpty(r))
- Tracing.Trace(" {0}", r);
- }
-
- residual = new System.Text.StringBuilder();
- }
- else
- {
- residual.Append(".");
- repeats++;
- }
-
- // if (repeats == 0)
- // Tracing.Trace(" check: {0}.*", stub);
-
- // check for exact match
- if (value.Equals(name))
- {
- return
- String.Format("(list \"{0}\" \"{1}\")",
- value,
- _assemblyForType[value]);
- }
- }
- }
-
- return "nil";
- }
-
-
-
-
- public static string GetConstructors (string typeName)
- {
- Tracing.Trace("GetConstructors: {0}", typeName);
- if (!_assemblyForType.Keys.Contains(typeName))
- {
- Tracing.Trace("GetConstructors: unknown assembly, found 0
constructors");
- return "nil";
- }
-
- Assembly a = AssemblyIsLoaded(_assemblyForType[typeName]);
- if (a==null)
- {
- Tracing.Trace("GetConstructors: could not load assembly, found
0 constructors");
-
- return "nil";
- }
-
- var tinfo= new Ionic.Cscomp.TypeInfo(a, typeName);
- return tinfo.GetConstructorsSexp();
- }
-
-
-
- public static string GetTypeGivenVarDecl (string csharpVarDeclaration)
- {
- return GetTypeGivenVarDecl(csharpVarDeclaration,
- null,
- null,
- -1,
- "Foo1", // classname
- "", "");
- }
-
-
- /// <summary>
- /// Get the type of the Nth variable in the declaration list.
- /// </summary>
- /// <remarks>
- /// <para>
- /// This method compiles the provided variable declaration list
- /// into an assembly, and then performs reflection on the result.
- /// </para>
- /// </remarks>
- ///
- /// <param name='csharpVarDeclaration'>
- /// a fragment of csharp code to compile. It should contain one or
- /// more variable declarations.
- /// </param>
- /// <param name='varIndex'>
- /// the number of the variable to determine the type of.
- /// There's no way to interrogate the type of a local var by
- /// name. That information is not in the assembly metadata -
- /// it's in the PDB, and it's not easily accessible. But, the
- /// MSIL apparently lists the local variables in the order in
- /// which they were declared. So we can use the index to find
- /// the desired local var.
- /// </param>
- /// <param name='namespaces'>
- /// a comma-separated list of namespaces
- /// </param>
- /// <param name='references'>
- /// a comma-separated list of assembly references
- /// </param>
- /// <param name='classname'>
- /// name of the class to use. Helpful in satisfying static
references.
- /// </param>
- /// <param name='arglist'>
- /// a comma-separated list of method types and arguments. This is
- /// a legal fragment of C# code, suitable to put right into the
method
- /// signature.
- /// </param>
- public static string GetTypeGivenVarDecl (string csharpVarDeclaration,
- String namespaces,
- String assemblyReferences,
- int varIndex,
- String classname,
- String arglist,
- String instanceMembers)
- {
- try
- {
- Tracing.Trace("GetTypeGivenVarDecl {0}", csharpVarDeclaration);
- foreach (string aName in namespaces.Split(','))
- {
- Tracing.Trace("Autoload assy {0}", aName);
- InternalLoadOneAssembly(aName);
- }
-
- Object compileResult = CompileFragment(csharpVarDeclaration,
- namespaces,
- assemblyReferences,
- classname,
- arglist,
- instanceMembers);
-
- MethodInfo methodInfo = compileResult as MethodInfo;
- if (methodInfo == null)
- {
- String[] emsgs = (String[]) compileResult;
- var estring = (emsgs!=null)
- ? String.Join("\" \"", emsgs)
- : String.Format("unknown error (cr = {0})",
-
(compileResult==null)?"-null-":compileResult.ToString());
- return String.Format("(list \"error\" \"{0}\")",
estring.Replace("\\", "\\\\"));
- }
-
-
- var res = GetTypeOfNthLocalVar(methodInfo,
varIndex).ToString();
- res = String.Format("(list \"type\" \"{0}\")", res);
-
- Tracing.Trace("GetTypeGivenVarDecl: result {0}", res);
-
- return res;
- }
- catch (System.Exception exc1)
- {
- Tracing.Trace("GetTypeGivenVarDecl Exception: {0}",
exc1.ToString());
- return String.Format ("(list \"exception\" \"{0}\")",
exc1.Message);
- }
- }
-
-
- public static String SetAssemblySearchPaths(String
commaDelimitedListOfPaths)
- {
- if (!String.IsNullOrEmpty(commaDelimitedListOfPaths))
- {
- SetBasicSearchPaths();
- _SearchPaths.AddRange(commaDelimitedListOfPaths
- .Split(",".ToCharArray(),
-
StringSplitOptions.RemoveEmptyEntries));
- }
-
- string atoms = String.Join("\" \"", _SearchPaths.ToArray());
- return "(list \"" + atoms.Replace("\\", "\\\\") + "\")";
- }
-
-
- /// <summary>
- /// Add one path to the list of assembly search paths
- /// </summary>
- /// <remarks>
- /// <para>
- /// If path is an empty string, no change will happen, but
- /// the caller will get the list of search paths in return.
- /// </para>
- /// </remarks>
- /// <returns>
- /// A lisp s-expression containing the list of search paths.
- /// </returns>
- public static String AddAssemblySearchPath(String path)
- {
- if (!String.IsNullOrEmpty(path))
- _SearchPaths.Add(path);
-
- string atoms = String.Join("\" \"", _SearchPaths.ToArray());
- return "(list \"" + atoms + "\")";
- }
-
-
- public static String GetAstForSourceFile(String filename)
- {
- Tracing.Trace("GetAstForSourceFile: {0}", filename);
- try
- {
- return AstUtils.CreateAstSexpression(filename);
- }
- catch (System.IO.FileNotFoundException)
- {
- return "(list 'error 'System.IO.FileNotFoundException)";
- }
- catch (System.Exception exc1)
- {
- Tracing.Trace("uncaught exception: {0}", exc1);
- System.Console.WriteLine("uncaught exception: {0}", exc1);
- }
- return "nil";
- }
-
-
-
- public static string FindAssemblyInSearchPaths(string filename)
- {
- if (File.Exists(filename)) return filename;
-
- var selection = from p in _SearchPaths
- where File.Exists(Path.Combine(p,filename))
- select Path.Combine(p,filename);
-
- if (selection.Count() >= 1)
- {
- Tracing.Trace("found assembly:{0}=>{1}", filename,
- selection.First());
- return "\"" + selection.First() + "\"";
- }
-
- Tracing.Trace("could not find assembly:{0}", filename);
- return "nil"; // cannot find
- }
-
-
-
- private static string GetShortAssemblyName(string ns)
- {
- switch (ns)
- {
- case "System.Text":
- return "System";
-
- case "System.Linq":
- return "System.Core";
-
- case "System.Web.Mvc.Ajax":
- return "System.Web.Mvc";
-
- case "System.Xml.Serialization":
- return "System.Xml";
-
- case "ICSharpCode.NRefactory.Ast":
- return "ICSharpCode.NRefactory";
-
- default:
- return ns;
- }
- }
-
-
-
-
- private static string GetShortDllName(string ns)
- {
- return GetShortAssemblyName(ns) + ".dll";
- }
-
-
-
- public static string GetAssemblyPathForNamespace(String ns)
- {
- Tracing.Trace("GetAssemblyPathForNamespace {0}", ns);
- var aname = GetShortAssemblyName(ns);
- Assembly a = AssemblyIsLoaded(aname);
- if (a!=null)
- {
- Tracing.Trace(" isloaded, location '{0}'", a.Location);
- return "\"" + a.Location.Replace("\\", "\\\\") + "\"";
- }
-
- Tracing.Trace(" looking in search paths");
- var result = FindAssemblyInSearchPaths(GetShortDllName(aname));
- if (result != null && result != "nil")
- return "\"" + result.Replace("\\", "\\\\") + "\"";
- return result;
- }
-
-
-
- private static string GetUsingClauses(IEnumerable<String> namespaces)
- {
- string s = "";
- foreach (var ns in namespaces)
- {
- if (!String.IsNullOrEmpty(ns))
- s += "using " + ns + ";\n";
- }
- return s;
- }
-
-
-
- /// <summary>
- /// Compile a C# var declaration fragment.
- /// </summary>
- /// <remarks>
- /// <para>
- /// The goal is to determine the types of the local variables,
- /// so that we can do completion on them.
- /// </para>
- /// </remarks>
- /// <param name='fragment'>
- /// a comma-separated list of namespaces
- /// </param>
- /// <param name='namespaces'>
- /// a comma-separated list of namespaces
- /// </param>
- /// <param name='references'>
- /// a comma-separated list of assembly references
- /// </param>
- /// <param name='classname'>
- /// name of the class to use. Helpful in satisfying static
references.
- /// </param>
- /// <param name='arglist'>
- /// a C# fragment, representing an arglist, suitable for
- /// framing within parens for the method declaration.
- /// </param>
- /// <returns>
- /// a MethodInfo, if success. Otherwise, an array of Strings
containing
- /// error messages.
- /// </returns>
- private static Object CompileFragment(string fragment,
- String namespaces,
- String references,
- string classname,
- String arglist,
- String instanceMembers)
- {
- string nsname = "N"+Path.GetRandomFileName().Replace(".","");
- string methodname = "M"+Path.GetRandomFileName().Replace(".","");
- //string classname = Path.GetRandomFileName().Replace(".","");
- string usingBlock = (String.IsNullOrEmpty(namespaces))
- ? "using System;\n"
- : GetUsingClauses(namespaces.Split(','));
- string literalSource =
- usingBlock +
- "\nnamespace " + nsname + " {" +
- "\n class " + classname + " {" +
- "\n " + instanceMembers.Replace("; ",";\n ")
- .Replace("} ","}\n ")
- .Replace(";}","; }") +
- "\n void "+ methodname + " (" + arglist + ") {"+
- "\n " + fragment.Replace(";",";\n ") +
- "\n " +
- "}\n }\n}\n";
-
- if (Verbose)
- System.Console.WriteLine("code to compile:\n{0}",
literalSource);
-
- Tracing.Trace("code to compile:\n{0}", literalSource);
-
- try
- {
- var csharp = new Microsoft.CSharp.CSharpCodeProvider(new
Dictionary<String, String> { { "CompilerVersion", "v3.5" } });
-
- var cp = new System.CodeDom.Compiler.CompilerParameters();
- cp.GenerateInMemory = true;
- cp.GenerateExecutable = false;
- cp.IncludeDebugInformation = true;
-
- if (!String.IsNullOrEmpty(references))
- foreach (string ra in references.Split(','))
- cp.ReferencedAssemblies.Add(ra);
-
- // do I need to worry about duplicates?
- foreach (string aName in namespaces.Split(','))
- {
- Tracing.Trace("maybe add Ref: {0}", aName);
- var path = GetAssemblyPathForNamespace(aName);
- if (path!=null && path != "nil")
- cp.ReferencedAssemblies.Add(path);
- }
-
- System.CodeDom.Compiler.CompilerResults cr =
- csharp.CompileAssemblyFromSource(cp,literalSource);
- if (cr == null)
- {
- var e = new List<String>();
- Tracing.Trace("CompilerResults == null");
- e.Add("CompilerResults == null");
- return e.ToArray();
- }
-
- foreach (string s in cr.Output)
- {
- if (Verbose)
- System.Console.WriteLine(s);
- Tracing.Trace(s);
- }
-
- if (cr.Errors.Count != 0)
- {
- var e = new List<String>();
- e.Add(String.Format("Errors.Count = {0}",
cr.Errors.Count));
- e.Add(cr.Errors[0].ToString());
- foreach(var error in cr.Errors)
- Tracing.Trace(error.ToString());
- return e.ToArray();
- }
-
- var a = cr.CompiledAssembly;
- MethodInfo mi = a.GetType(nsname + "." + classname)
- .GetMethod(methodname, BindingFlags.Instance |
BindingFlags.NonPublic);
-
- return mi;
- }
- catch (System.Exception e1)
- {
- var e = new List<String>();
- e.Add("Exception during compile: " + e1.ToString() );
- Tracing.Trace("{0}", e1.ToString());
- return e.ToArray();
- }
- }
-
-
-
- /// <summary>
- /// Get the type of the Nth local variable in the given method.
- /// </summary>
- /// <remarks>
- /// <para>
- /// Reflection doesn't provide access to var names. And,
- /// some variables listed in LocalVariables are synthetic -
- /// generated by the compiler. But apparently the IL does
- /// list the format local vars first, and in the order in
- /// which they are declared. So, to retrieve a local var,
- /// rely on the count.
- /// </para>
- /// </remarks>
- private static Type GetTypeOfNthLocalVar(MethodInfo methodInfo, int ix)
- {
- MethodBody body = methodInfo.GetMethodBody();
- var localVars = body.LocalVariables;
- Type ft = null;
- int c = 0;
- foreach (LocalVariableInfo lvi in localVars)
- {
- if (Verbose)
- System.Console.WriteLine("Local var [{0}] {1}",
- c, lvi.LocalType.ToString());
- if (c==ix || ix < 0)
- ft = lvi.LocalType;
- c++;
- }
- return ft;
- }
-
- private static bool _Verbose;
- public static bool Verbose
- {
- get
- {
- return _Verbose;
- }
- set
- {
- if (value)
- {
- // turn on
- Tracing.Trace("Verbose = true");
- }
- _Verbose = value;
- }
- }
- }
-
-
-
- public class TypeInfo
- {
- internal TypeInfo(Assembly a, string typeName)
- {
- mt = a.GetType(typeName, false, true);
- if ( mt == null )
- throw new Exception(String.Format("Cannot get that type
({0})", typeName));
- }
-
- /// <summary>
- /// Returns the TypeInfo as a lisp S-expression.
- /// </summary>
- /// <remarks>
- /// <para>
- /// It looks like this:
- ///
- /// </para>
- /// </remarks>
- internal String AsSexp()
- {
- var result= new System.Text.StringBuilder();
- result.Append("(list \"").Append(mt.FullName).Append("\" 'type
(list ");
-
- // properties
- var props = GetPropertiesInfo();
- if (props != null)
- {
- foreach (string s in props)
- result.Append(s);
- }
-
- result.Append(") (list ");
-
- // methods
- var meth = GetMethodsInfo();
- if (meth != null)
- {
- foreach (string s in meth)
- result.Append(s);
-
- }
- result.Append(") (list ");
-
-
- // fields
- var fields = GetFieldsInfo();
- if (fields != null)
- {
- foreach (string s in fields)
- result.Append(s);
-
- }
- result.Append(")");
-
- // events? constructors?
-
- result.Append(")");
- return result.ToString();
- }
-
- // public String LastError { get { return lastError;} }
- // public Type TheType { get { return mt; } }
- // public String FQN { get { return (mt!=null) ?
mt.AssemblyQualifiedName: null; } }
- // public String Name { get { return (mt!=null) ? mt.Name:
null;} }
- // public String FullName { get { return (mt != null) ?
mt.FullName : null;} }
- // public String Status { get { return status;} }
-
- // public String Href
- // {
- // set { theHref= value; }
- // get { return theHref; }
- // }
-
- private static Type ReferencedType(Type t)
- {
- return (t.HasElementType) ? ReferencedType(t.GetElementType()) : t
;
- }
-
- private static String EmitOneType(Type t1)
- {
- return t1.ToString();
- }
-
-
- private static String EmitOneTypeWithInterfaces(Type t1)
- {
- Type t= ReferencedType(t1);
- var result= new System.Text.StringBuilder();
- result.Append(t1.ToString());
-
- Type[] it= t.GetInterfaces();
- if (it.Length > 0 )
- {
- int j=0;
- for (int i=0; i < it.Length; i++)
- {
- if ((t.BaseType!=null) &&
!(it[i].IsAssignableFrom(t.BaseType)))
- {
- if (j==0) result.Append(" : ");
- else result.Append(", ");
- result.Append(EmitOneType(it[i]));
- j++;
- }
- }
- }
-
- return result.ToString();
- }
-
-
-
- private string ParamString(System.Reflection.ParameterInfo[] pi, bool
isProperty)
- {
- if (pi.Length==0) return "nil";
-
- var sb= new System.Text.StringBuilder("(list ");
- int j;
- String openBracket= "(";
- String closeBracket= ")";
- if (isProperty)
- {
- openBracket= "[";
- closeBracket= "]";
- }
-
- for (j=0; j < pi.Length; j++)
- {
- // ParameterAttributes Attributes = pi[j].Attributes;
- // if (Attributes != ParameterAttributes.None)
- // sb.Append("[").Append(Attributes.ToString()).Append("]
"); // eg, In,Out,Optional
-
- sb.Append("\"").Append(pi[j].ParameterType.ToString())
- .Append(" ")
- .Append(pi[j].Name)
- .Append("\" ");
- }
- if (isProperty)
- {
- if (j!=0) sb.Append(closeBracket);
- }
- else
- {
- if (j==0) sb.Append(openBracket);
- sb.Append(closeBracket);
- }
-
- return sb.ToString();
- }
-
-
- private string NewParamString(System.Reflection.ParameterInfo[] pi)
- {
- if (pi.Length==0) return "nil";
- var sb= new System.Text.StringBuilder("(list ");
- for (int j=0; j < pi.Length; j++)
- {
- sb.Append("(list \"")
- .Append(pi[j].Name)
- .Append("\" 'variable (list :type \"")
- .Append(pi[j].ParameterType.ToString())
- .Append("\")) ");
- }
- sb.Append(")");
- return sb.ToString();
- }
-
-
- private static String EmitAttributes(Type t) {
- System.Text.StringBuilder result= new System.Text.StringBuilder();
- if (t.IsSerializable) result.Append("[serializable]<br>\n ");
- if (t.IsPublic) result.Append("public ");
- if (t.IsAbstract) result.Append("abstract ");
- if (t.IsSealed) result.Append("sealed ");
- if (t.IsClass) result.Append("class ");
- if (t.IsEnum) result.Append("enum ");
- if (t.IsInterface) result.Append("interface ");
- return result.ToString();
- }
-
-
- internal String GetConstructorsSexp()
- {
- if (mt==null)
- {
- Tracing.Trace("{0}: no type?", mt.FullName);
- return "nil";
- }
- System.Reflection.ConstructorInfo[] cia= mt.GetConstructors();
- if (cia==null) return "nil";
- if (cia.Length==0)
- {
- Tracing.Trace("{0}: No constructors for that type",
mt.FullName);
- return "nil";
- }
-
- Tracing.Trace("{1}: Found {0} constructors", cia.Length,
mt.FullName);
-
- var sb1 = new System.Text.StringBuilder();
- sb1.Append("(list \"").Append(mt.FullName)
- .Append("\" 'type (list :constructors (list\n");
-
- foreach (ConstructorInfo ci in cia)
- {
- sb1.Append(" (list :typemodifiers ")
- .Append(NewMethodBaseModifiers(ci))
- .Append(" :arguments ")
- .Append(NewParamString(ci.GetParameters()))
- .Append(")\n");
- }
- sb1.Append(")))");
- return sb1.ToString();
- }
-
-
-
- private String PropertyModifiers(PropertyInfo p)
- {
- var sb= new System.Text.StringBuilder("(cons 'typemodifiers (list
");
- System.Reflection.MethodInfo mi= null;
-
- if (p.GetGetMethod() != null)
- {
- mi= p.GetGetMethod();
- if (p.GetSetMethod() == null)
- sb.Append("\"readonly\" ");
- }
- else if (p.GetSetMethod() != null) {
- mi= p.GetSetMethod();
- sb.Append("\"writeonly\" ");
- }
-
- if (mi != null) {
- if (mi.IsPublic)
- sb.Append("\"public\" ");
- if (mi.IsPrivate)
- sb.Append("\"private\" ");
- if (mi.IsFamily)
- sb.Append("\"protected\" ");
-
- if (mi.IsStatic)
- sb.Append("\"static\" ");
- }
-
- sb.Append("))");
- return sb.ToString();
- }
-
-
- private String[] GetPropertiesInfo()
- {
- if (mt==null) return null;
- System.Reflection.PropertyInfo[] pi= mt.GetProperties();
- if (pi==null) return null;
- if (pi.Length==0) return null;
-
- var a= new List<String>();
- System.Text.StringBuilder sb1;
- foreach (PropertyInfo p in pi) {
-
- sb1 = new System.Text.StringBuilder();
- sb1.Append("(list \"").Append(p.Name).Append("\" 'property ");
-
- sb1.Append("\"").Append(p.PropertyType.ToString()).Append("\"
");
-
- sb1.Append(PropertyModifiers(p));
-
- sb1.Append(")");
-
- a.Add(sb1.ToString());
- }
- return a.ToArray();
- }
-
-
-
- private String EmitMethodAttrs(MethodInfo m) {
- System.Text.StringBuilder result= new System.Text.StringBuilder();
-
- if (m.IsPublic)
- result.Append("public ");
-
- if (m.IsFamily)
- result.Append("protected ");
-
- if (m.IsPrivate)
- result.Append("private ");
-
- if (m.IsAbstract)
- result.Append("abstract ");
-
- if (m.IsStatic)
- result.Append("static ");
-
- if (m.IsFinal)
- result.Append("final ");
-
- return result.ToString();
- }
-
-
-
- public String[] GetMethodsInfo()
- {
- System.Reflection.MethodInfo[] mi= mt.GetMethods();
- System.Array.Sort(mi,new MpfComparer());
- var a= new List<String>();
- System.Text.StringBuilder sb1;
- foreach (MethodInfo m in mi)
- {
- sb1= null;
-
- if (m.IsPrivate) continue;
-
- // special name denotes???? I don't know.
- if (!m.IsSpecialName)
- {
- // it's a method:
- sb1 = new System.Text.StringBuilder(" (list \"");
- sb1.Append(m.Name).Append("\" 'method ")
-
.Append("\"").Append(m.ReturnType.ToString()).Append("\" ")
- .Append(ParamString(m.GetParameters(), false))
- .Append(MethodBaseModifiers(m))
- .Append(")");
- }
-
- if (sb1 != null)
- a.Add(sb1.ToString());
- }
- return a.ToArray();
- }
-
-
-
- private string MethodBaseModifiers(MethodBase mi)
- {
- var sb= new System.Text.StringBuilder(" (cons 'typemodifiers (list
");
- if (mi.IsFinal)
- sb.Append("\"sealed\" ");
- if (mi.IsPublic)
- sb.Append("\"public\" ");
- if (mi.IsPrivate)
- sb.Append("\"private\" ");
- if (mi.IsFamily)
- sb.Append("\"protected\" ");
- if (mi.IsStatic)
- sb.Append("\"static\" ");
- sb.Append("))");
- return sb.ToString();
- }
-
-
- private string NewMethodBaseModifiers(MethodBase mi)
- {
- var sb= new System.Text.StringBuilder(" (list ");
- if (mi.IsFinal)
- sb.Append("\"sealed\" ");
- if (mi.IsPublic)
- sb.Append("\"public\" ");
- if (mi.IsPrivate)
- sb.Append("\"private\" ");
- if (mi.IsFamily)
- sb.Append("\"protected\" ");
- if (mi.IsStatic)
- sb.Append("\"static\" ");
- sb.Append(")");
- return sb.ToString();
- }
-
-
- // private void BuildClassHierarchy(Type t) {
- // classHierarchy.Push(t);
- // if (t.BaseType != null)
- // BuildClassHierarchy(t.BaseType);
- // }
-
-
- // public String GetHierarchyHtml() {
- // if (mt == null) return null;
- // classHierarchy= new Stack();
- // BuildClassHierarchy(mt);
- // int c= classHierarchy.Count;
- // System.Text.StringBuilder sb= new
System.Text.StringBuilder("\n");
- // int i=0;
- // while (classHierarchy.Count != 0) {
- // sb.Append("<div class='elt'>");
- // if (i!=0) sb.Append("+ ");
- //
sb.Append(EmitOneTypeWithInterfaces((Type)classHierarchy.Pop())).Append("\n");
- // i++;
- // }
- // for (i=0; i < c; i++) sb.Append("</div>");
-
- // return sb.ToString();
- // }
-
-
-
-
- // public String[] GetPropertiesHtml() {
- // if (mt == null) return null;
- // System.Reflection.PropertyInfo[] pi= mt.GetProperties();
- // System.Array.Sort(pi,new myComparer()); // by name
- // ArrayList a= new ArrayList();
- // System.Text.StringBuilder sb1;
- // foreach (PropertyInfo p in pi) {
- // try{
- // sb1 = new System.Text.StringBuilder();
- // sb1.Append(" ").Append(PropAttrsString(p));
- // sb1.Append(" ").Append(EmitOneType(p.PropertyType));
- // sb1.Append(" <b>").Append(p.Name).Append("</b>");
- // AppendParams(sb1,p.GetIndexParameters(), true);
- // }
- // catch(Exception e){
- // a.Add(e.Message);
- // continue;
- // }
- // a.Add(sb1.ToString());
- // }
- // return (String[]) a.ToArray(typeof(String));
- // }
-
-
-
- private static String FieldAttrsString(FieldInfo f)
- {
- var sb= new System.Text.StringBuilder(" (cons 'typemodifiers (list
");
- if (f.IsPublic)
- sb.Append("\"public\" ");
- if (f.IsFamily)
- sb.Append("\"protected\" ");
- if (f.IsPrivate)
- sb.Append("\"private\" ");
- if (f.IsLiteral)
- sb.Append("\"const\" ");
- if (f.IsStatic)
- sb.Append("\"static\" ");
- sb.Append("))");
- return sb.ToString();
- }
-
-
- public String[] GetFieldsInfo()
- {
- if (mt == null) return null;
- System.Reflection.FieldInfo[] fi= mt.GetFields();
- System.Array.Sort(fi,new MpfComparer()); // by name
- var a= new List<String>();
- System.Text.StringBuilder sb1;
- foreach (FieldInfo f in fi)
- {
- if (!f.IsPrivate)
- {
- try
- {
- sb1 = new System.Text.StringBuilder(" (list \"");
- sb1.Append(f.Name).Append("\" 'field ")
-
.Append("\"").Append(f.FieldType.ToString()).Append("\" ")
- .Append(FieldAttrsString(f))
- .Append(")");
- }
- catch(Exception e){
- a.Add(e.Message);
- continue;
- }
- if (sb1 != null)
- a.Add(sb1.ToString());
- }
- }
- return a.ToArray();
- }
-
- private System.Type mt;
- }
-
-
-
- public class MpfComparer : System.Collections.IComparer
- {
- static Type mi= typeof(MethodInfo);
- static Type pi= typeof(PropertyInfo);
- static Type fi= typeof(FieldInfo);
-
- public int Compare (Object x, Object y)
- {
- if (mi.IsInstanceOfType(x)) {
- MethodInfo i1= (MethodInfo) x;
- MethodInfo i2= (MethodInfo) y;
- return i1.Name.CompareTo(i2.Name);
- }
-
- if (pi.IsInstanceOfType(x)) {
- PropertyInfo i1= (PropertyInfo) x;
- PropertyInfo i2= (PropertyInfo) y;
- return i1.Name.CompareTo(i2.Name);
- }
- if (fi.IsInstanceOfType(x)) {
- FieldInfo i1= (FieldInfo) x;
- FieldInfo i2= (FieldInfo) y;
- return i1.Name.CompareTo(i2.Name);
- }
-
- return 0;
- }
- }
-
-
- internal static class Tracing
- {
-#if UseCopyData
- private static Ionic.CopyData.Transceiver transceiver;
- private static bool _initialized;
-#endif
-
- [Conditional("CscompTrace")]
- private static void SetupDebugConsole()
- {
-#if UseCopyData
-
- // use object initializer syntax
- System.Diagnostics.Process p3 = new System.Diagnostics.Process
- {
- StartInfo =
- {
- FileName =
"c:\\dev\\vsp\\UnitTestProgressMonitor\\UnitTestProgressMonitor\\bin\\Debug\\UnitTestProgressMonitor.exe",
- Arguments = "-channel CscompShell",
- CreateNoWindow = false,
- UseShellExecute = false
- }
- };
- p3.Start();
-
- // wait for the process to start?
- System.Threading.Thread.Sleep(650);
-
- transceiver = new Ionic.CopyData.Transceiver();
- transceiver.Channel = "CscompShell";
-
- transceiver.Send("title *CscompShell* Trace Monitor");
-
- System.Threading.Thread.Sleep(400);
- transceiver.Send("log Hello from CscompShell");
-
- _initialized = true;
-#endif
- }
-
-
- [Conditional("CscompTrace")]
- public static void Trace(string format, params object[] args)
- {
-#if UseCopyData
- if (!_initialized)
- {
- SetupDebugConsole();
- }
-
- var s2 = String.Format(format, args);
- transceiver.Send("log " + s2);
-#endif
- }
- }
-
-
- static class AstUtils
- {
-
- internal static string CreateAstSexpression(string filename)
- {
- using (var fs = File.OpenRead(filename))
- {
- using (var parser =
ParserFactory.CreateParser(SupportedLanguage.CSharp,
- new
StreamReader(fs)))
- {
- parser.Parse();
-
- // RetrieveSpecials() returns an IList<ISpecial>
- // parser.Lexer.SpecialTracker.RetrieveSpecials()...
- // "specials" == comments, preprocessor directives, etc.
-
- // parser.CompilationUnit retrieves the root node of the
result AST
- return
SexpressionGenerator.Generate(parser.CompilationUnit).ToString();
-
- // if (parser.Errors.Count > 0)
- // {
- // MessageBox.Show(parser.Errors.ErrorOutput, "Parse
errors");
- // }
- }
- }
- }
-
-
- sealed class Nonce
- {
- private readonly static Nonce _instance = new Nonce();
- public static Nonce Instance { get { return _instance; } }
-
- int value;
- public int Value
- {
- get
- {
- return value++;
- }
- }
- private Nonce()
- {
- value = 1;
- }
- }
-
-
- class SexpressionGenerator
- {
- private int depth = 0;
- private StringBuilder sb1;
-
- static internal StringBuilder
Generate(ICSharpCode.NRefactory.Ast.AbstractNode node)
- {
- var sexp = new SexpressionGenerator();
- return sexp.NodeToStringBuilder(node, null);
- }
-
-
- private void EmitModifier (AttributedNode anode)
- {
- sb1.Append('\n')
- .Append(new String(' ', 2*depth + 2))
- .Append("(modifier \"");
- if (anode.Modifier.ToString() != "None")
-
sb1.Append(anode.Modifier.ToString().ToLower().Replace(",",""));
- sb1.Append("\") ");
- }
-
- private void EmitParameters(ParametrizedNode pnode)
- {
- string indent = new String(' ', 2*depth + 2);
- sb1.Append('\n')
- .Append(indent)
- .Append("(params");
- if (pnode.Parameters == null || pnode.Parameters.Count == 0)
- {
- sb1.Append(" nil)");
- }
- else
- {
- foreach (var p in pnode.Parameters)
- {
- sb1.Append('\n')
- .Append(indent)
- .Append(" (var \"")
- .Append(p.ParameterName)
- .Append("\" \"")
- .Append(p.TypeReference.ToString())
- .Append("\" ");
- EmitLocation(p.StartLocation, p.EndLocation, false);
- EmitId();
- sb1.Append(')');
- }
- sb1.Append(')');
- }
- }
-
- private void EmitId()
- {
- sb1.Append(" (id ")
- .Append(Nonce.Instance.Value)
- .Append(')');
- }
-
- private void EmitLocation(Location start, Location end)
- {
- EmitLocation(start, end, true);
- }
-
-
- private void EmitLocation(Location start, Location end, bool
indent)
- {
- if (indent)
- sb1.Append(new String(' ', 2*depth + 2));
-
- if (end.Line!=0 || end.Column !=0)
- {
- sb1.Append("(location (")
- .Append(start.Line.ToString())
- .Append(' ')
- .Append(start.Column.ToString())
- .Append(") (")
- .Append(end.Line.ToString())
- .Append(' ')
- .Append(end.Column.ToString())
- .Append("))");
- }
- }
-
-
- private void EmitSet<T>(string label, List<T> list, Action<T>
emitOne)
- {
- var count = list.Count;
- if (count == 1)
- {
- emitOne(list[0]);
- }
- else
- {
- depth+=2;
- sb1.Append('(')
- .Append(label)
- .Append("set nil\n")
- .Append(new String(' ', 2*depth-2))
- .Append("(children");
- foreach (var item in list)
- {
- sb1.Append('\n')
- .Append(new String(' ', 2*depth));
- emitOne(item);
- sb1.Append(')');
- }
- sb1.Append(")");
- depth-=2;
- }
- }
-
-
- private StringBuilder
NodeToStringBuilder(ICSharpCode.NRefactory.Ast.AbstractNode node)
- {
- return NodeToStringBuilder(node, null);
- }
-
-
-
- private void EmitImport (ICSharpCode.NRefactory.Ast.Using u1)
- {
- sb1.Append("(import \"")
- .Append(u1.Name)
- .Append('"');
- if (u1.Alias.ToString().Contains("NullTypeReference"))
- sb1.Append(" nil");
- else
- sb1.Append(" \'").Append(u1.Alias.ToString()).Append('\'');
- }
-
-
- private StringBuilder
NodeToStringBuilder(ICSharpCode.NRefactory.Ast.AbstractNode node, string
overrideBlock)
- {
- BlockStatement body = null;
- var t = node.GetType();
- bool empty = false;
- if (sb1 == null)
- sb1 = new StringBuilder();
-
- depth++;
-
- sb1.Append(new String(' ', 2*depth));
- if (t == typeof(ICSharpCode.NRefactory.Ast.CompilationUnit))
- {
- sb1.Append("'(CompilationUnit");
- }
- else if (t ==
typeof(ICSharpCode.NRefactory.Ast.UsingDeclaration))
- {
- var u = node as
ICSharpCode.NRefactory.Ast.UsingDeclaration;
- EmitSet("import", u.Usings, EmitImport);
- }
- else if (t ==
typeof(ICSharpCode.NRefactory.Ast.AttributeSection))
- {
- var a = node as
ICSharpCode.NRefactory.Ast.AttributeSection;
- var emitOne = new
Action<ICSharpCode.NRefactory.Ast.Attribute>((a1)=>
- {
- sb1.Append("(attribute \"")
- .Append(a1.Name)
- .Append("\" ")
- .Append(a.AttributeTarget);
-
- foreach (var pa1 in a1.PositionalArguments)
- {
- var pa = pa1 as PrimitiveExpression;
- if (pa!=null)
- {
- sb1.Append(" \"")
- .Append(pa.Value.ToString())
- .Append("\" ");
- }
- }
- });
- EmitSet("attribute", a.Attributes, emitOne);
- //sb1.Append(node.ToString());
- }
- else if (t ==
typeof(ICSharpCode.NRefactory.Ast.NamespaceDeclaration))
- {
- var ns = node as
ICSharpCode.NRefactory.Ast.NamespaceDeclaration;
- sb1.Append("(namespace \"");
- sb1.Append(ns.Name)
- .Append('\"');
- //body = ns.Body;
- }
- else if (t ==
typeof(ICSharpCode.NRefactory.Ast.TypeDeclaration))
- {
- var type = node as
ICSharpCode.NRefactory.Ast.TypeDeclaration;
- sb1.Append("(type \"");
- sb1.Append(type.Name)
- .Append("\" ");
- EmitModifier(type);
- //sb1.Append(node.ToString());
- }
- else if (t ==
typeof(ICSharpCode.NRefactory.Ast.ConstructorDeclaration))
- {
- var ctor = node as
ICSharpCode.NRefactory.Ast.ConstructorDeclaration;
- sb1.Append("(ctor \"");
- sb1.Append(ctor.Name)
- .Append("\" ");
- EmitModifier(ctor);
- EmitParameters(ctor);
- body = ctor.Body;
- //sb1.Append(node.ToString());
- }
- else if (t ==
typeof(ICSharpCode.NRefactory.Ast.MethodDeclaration))
- {
- var m = node as
ICSharpCode.NRefactory.Ast.MethodDeclaration;
- sb1.Append("(method \"");
- sb1.Append(m.Name)
- .Append("\" \"")
- .Append(m.TypeReference)
- .Append("\" ");
- EmitModifier(m);
- EmitParameters(m);
- body = m.Body;
- //sb1.Append(node.ToString());
- }
- else if (t ==
typeof(ICSharpCode.NRefactory.Ast.LocalVariableDeclaration))
- {
- var lvd = node as
ICSharpCode.NRefactory.Ast.LocalVariableDeclaration;
- var count = lvd.Variables.Count;
- var emitOne = new Action<VariableDeclaration>((v1) => {
- sb1.Append("(var \"")
- .Append(v1.Name)
- .Append("\" \"")
- .Append(lvd.TypeReference.ToString())
- .Append("\" ");
- //EmitModifier(lvd, sb1, depth);
- });
-
- EmitSet("var", lvd.Variables, emitOne);
- //sb1.Append(node.ToString());
- }
- else if (t ==
typeof(ICSharpCode.NRefactory.Ast.FieldDeclaration))
- {
- var f = node as
ICSharpCode.NRefactory.Ast.FieldDeclaration;
- var count = f.Fields.Count;
- var emitOne = new Action<VariableDeclaration>((f1) => {
- sb1.Append("(field \"")
- .Append(f1.Name)
- .Append("\" \"")
- .Append(f.TypeReference)
- .Append("\" ");
- EmitModifier(f);
- });
-
- EmitSet("field", f.Fields, emitOne);
- //sb1.Append(node.ToString());
- }
- else if (t ==
typeof(ICSharpCode.NRefactory.Ast.PropertyDeclaration))
- {
- var pd = node as
ICSharpCode.NRefactory.Ast.PropertyDeclaration;
- var emitPropGetSet = new Action<PropertyGetSetRegion> ((r)
=> {
- depth++;
- Type t1 = r.GetType();
- String s = (t1 ==
typeof(ICSharpCode.NRefactory.Ast.PropertyGetRegion))
- ? "get" : "set";
-
- string indent = new String(' ', 2*depth);
- sb1.Append('\n')
- .Append(indent)
- .Append('(')
- .Append(s)
- .Append(' ');
- if (r.Modifier.ToString() != "None")
- EmitModifier(r);
-
- if (!r.IsNull && (r.Block != BlockStatement.Null))
- {
- if (t1 ==
typeof(ICSharpCode.NRefactory.Ast.PropertySetRegion))
- {
- sb1.Append('\n')
- .Append(indent)
- .Append(" (params (var \"value\" \"")
- .Append(pd.TypeReference)
- .Append("\" ");
- EmitLocation(r.StartLocation,
r.EndLocation, false);
- EmitId();
- sb1.Append(")) ");
- }
-
- sb1.Append('\n');
- NodeToStringBuilder(r.Block);
- sb1.Append('\n');
- EmitLocation(r.Block.StartLocation,
r.Block.EndLocation);
- EmitId();
- }
- depth--;
- sb1.Append(')');
- });
-
- sb1.Append("(property \"")
- .Append(pd.Name)
- .Append("\" \"")
- .Append(pd.TypeReference)
- .Append("\" ");
- EmitModifier(pd);
-
- if (pd.HasGetRegion)
- emitPropGetSet(pd.GetRegion);
-
- if (pd.HasSetRegion)
- emitPropGetSet(pd.SetRegion);
-
- // xxx
- //sb1.Append('\n');
- //sb1.Append(node.ToString());
- }
- else if (t ==
typeof(ICSharpCode.NRefactory.Ast.TryCatchStatement))
- {
- var tc = node as
ICSharpCode.NRefactory.Ast.TryCatchStatement;
- sb1.Append("(trycatch\n");
- //sb1.Append(tc.StatementBlock.ToString());
- NodeToStringBuilder(tc.StatementBlock, "(try");
- foreach (var cc1 in tc.CatchClauses)
- {
- var cc = cc1 as CatchClause;
- if (cc!=null)
- {
- sb1.Append('\n')
- .Append(new String(' ', 2*depth + 2))
- .Append("(catch (var \"")
- .Append(cc.VariableName)
- .Append("\" \"")
- .Append(cc.TypeReference)
- .Append("\" ");
- EmitLocation(cc.StartLocation, cc.EndLocation,
false);
- EmitId();
- sb1.Append(")\n");
- NodeToStringBuilder(cc.StatementBlock, "");
- sb1.Append(')');
- }
- }
- if (tc.FinallyBlock as BlockStatement != null)
- {
- sb1.Append('\n');
- NodeToStringBuilder(tc.FinallyBlock, "(finally");
- }
- }
- else if (t ==
typeof(ICSharpCode.NRefactory.Ast.BlockStatement))
- {
- // var bs = node as
ICSharpCode.NRefactory.Ast.BlockStatement;
- // children will be emitted below.
- // remove the indent that was added above.
- if (!String.IsNullOrEmpty(overrideBlock))
- sb1.Append(overrideBlock);
- else if (overrideBlock != "")
- sb1.Append("(block");
- else
- {
- sb1.Length -= 2*depth+1;
- empty = true;
- }
- }
- else if (t ==
typeof(ICSharpCode.NRefactory.Ast.ExpressionStatement))
- {
- // then or else
- if (!String.IsNullOrEmpty(overrideBlock))
- sb1.Append(overrideBlock);
- else
- sb1.Append("(expression ");
- }
- else if (t ==
typeof(ICSharpCode.NRefactory.Ast.ReturnStatement))
- {
- sb1.Append("(return ");
- }
- else if (t ==
typeof(ICSharpCode.NRefactory.Ast.IfElseStatement))
- {
- var ifelse = node as
ICSharpCode.NRefactory.Ast.IfElseStatement;
- sb1.Append("(if ");
- //sb1.Append(node.ToString());
- foreach (var s in ifelse.TrueStatement)
- {
- sb1.Append('\n');
- NodeToStringBuilder(s, "(then");
- }
- if (ifelse.HasElseIfSections)
- {
- foreach (var s in ifelse.ElseIfSections)
- {
- sb1.Append('\n');
- NodeToStringBuilder(s.EmbeddedStatement,
"(elseif");
- }
- }
- if (ifelse.HasElseStatements)
- {
- foreach (var s in ifelse.FalseStatement)
- {
- //sb1.Append("++\n");
- sb1.Append('\n');
- NodeToStringBuilder(s, "(else");
- }
- }
- }
- else if (t ==
typeof(ICSharpCode.NRefactory.Ast.ForeachStatement))
- {
- var stmt = node as
ICSharpCode.NRefactory.Ast.ForeachStatement;
- var expr = stmt.Expression;
-
- sb1.Append("(foreach (var \"")
- .Append(stmt.VariableName)
- .Append("\" \"")
- .Append(stmt.TypeReference.ToString());
- sb1.Append("\" ");
- // location of the variable initialization
- EmitLocation(expr.StartLocation, expr.EndLocation, false);
- // xxx
- //EmitLocation(stmt.StartLocation, expr.EndLocation,
false);
- EmitId();
- sb1.Append(")\n");
-
- //sb1.Append(node.ToString());
- NodeToStringBuilder(stmt.EmbeddedStatement);
- }
- else if (t == typeof(ICSharpCode.NRefactory.Ast.ForStatement))
- {
- var fs = node as ICSharpCode.NRefactory.Ast.ForStatement;
- sb1.Append("(for \n");
- foreach (var stmt in fs.Initializers)
- {
- NodeToStringBuilder(stmt);
- }
- sb1.Append("\n");
- NodeToStringBuilder(fs.EmbeddedStatement);
- //sb1.Append(node.ToString());
- }
- else if (t ==
typeof(ICSharpCode.NRefactory.Ast.SwitchStatement))
- {
- var ss = node as
ICSharpCode.NRefactory.Ast.SwitchStatement;
- sb1.Append("(switch ");
- //sb1.Append(node.ToString());
- }
- else if (t ==
typeof(ICSharpCode.NRefactory.Ast.ThrowStatement))
- {
- //var ts = node as
ICSharpCode.NRefactory.Ast.ThrowStatement;
- sb1.Append("(throw ");
- }
- else if (t ==
typeof(ICSharpCode.NRefactory.Ast.UsingStatement))
- {
- var us = node as ICSharpCode.NRefactory.Ast.UsingStatement;
- sb1.Append("(using \n");
- NodeToStringBuilder(us.ResourceAcquisition);
- sb1.Append("\n");
- NodeToStringBuilder(us.EmbeddedStatement);
- }
- else
- {
- // all others
- sb1.Append("(")
- .Append(t.ToString())
- .Append(" ")
- .Append(node.ToString());
- }
-
-
- if (node.Children != null &&
- ((t == typeof(ICSharpCode.NRefactory.Ast.BlockStatement))
||
- node.Children.Count > 0))
- {
- int count = node.Children.Count;
- int n = 0;
-
- if (t != typeof(ICSharpCode.NRefactory.Ast.BlockStatement))
- {
- sb1.Append('\n')
- .Append(new String(' ', 2*depth+2))
- .Append("(children");
- depth++;
- }
- foreach (var c in node.Children)
- {
- if (n == 0)
- sb1.Append('\n');
- NodeToStringBuilder(c as AbstractNode);
- n++;
- if (n < count)
- sb1.Append('\n');
- }
- if (count == 0)
- sb1.Append(' ');
- if (t != typeof(ICSharpCode.NRefactory.Ast.BlockStatement))
- {
- sb1.Append(")");
- depth--;
- }
- }
-
- if (t != typeof(ICSharpCode.NRefactory.Ast.CompilationUnit))
- {
- sb1.Append('\n');
- //sb1.Append("--\n"); // debugging only
-
- // some structures have a body - like methods, ctors, etc.
- if (body != null)
- {
- // emit body as well
- NodeToStringBuilder(body as AbstractNode);
-
- //sb1.Append("::\n")
- sb1.Append('\n');
- EmitLocation(node.StartLocation, body.EndLocation);
- }
-
- // special case properties, because they are special!
- else if (t ==
typeof(ICSharpCode.NRefactory.Ast.PropertyDeclaration))
- {
- var p = node as
ICSharpCode.NRefactory.Ast.PropertyDeclaration;
- EmitLocation(node.StartLocation, p.BodyEnd);
- }
-
- else
- {
- EmitLocation(node.StartLocation, node.EndLocation);
- }
- }
-
- if (!empty)
- {
- EmitId();
- sb1.Append(')');
- }
- depth--;
- return sb1;
- }
- }
- }
-
-
-}
-
-
-
-
-/*
-
-
-
- [Ionic.Cscomp.Utilities]::GetTypeGivenVarDecl(' var foo = "this is a
string"; var fred = new System.Collections.Generic.List<String> { foo,
foo.Length.ToString() }; var z = fred.Count; var mmm = count + 8; var nnn =
mmm.ToString() +
this.InstanceMethod1(count);','System,System.Xml,System.IO','',4,'CsharpCompletion','int
count','private static int staticField1 = default(int); string
InstanceMethod1(int index) { return default(string);} ')
-
-
- [Ionic.Cscomp.Utilities]::GetConstructors("System.String");
-
- [Ionic.Cscomp.Utilities]::GetConstructors("System.DateTimeKind");
-
- [Ionic.Cscomp.Utilities]::GetMatches("DateT", "System,System.IO");
-
-
-
- [Ionic.Cscomp.Utilities]::QualifyType("System.Collections.Generic.List`1");
-
- [Ionic.Cscomp.Utilities]::GetTypeInfo("System.Collections.Generic.List");
-
- [Ionic.Cscomp.Utilities]::GetTypeGivenVarDecl('var x = String.Format("{0}",
928);' )
-
- [Ionic.Cscomp.Utilities]::GetTypeGivenVarDecl('var x = new
System.Collections.Generic.List<string>();')
-
-
-
- [Ionic.Cscomp.Utilities]::GetTypeGivenVarDecl(' var doo = "Tra la la"; var
fred = new System.Collections.Generic.List<String>
- {
- doo.Length.ToString()
- };');
-
- [Ionic.Cscomp.Utilities]::GetTypeGivenVarDecl(' var doo = "Tra la la"; var
fred = new System.Collections.Generic.List<String> { doo.Length.ToString() };',
$null, $null, 2);
-
-
-
-
[Ionic.Cscomp.Utilities]::GetTypeInfo("System.Data.SqlClient.SqlCommand","System.Data,
Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
-
- [Ionic.Cscomp.Utilities]::GetTypeInfo("System.Xml.XmlReader","System.Xml,
Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
-
-
- [Ionic.Cscomp.Utilities]::GetTypeInfo("System.DateTime");
-
- [Ionic.Cscomp.Utilities]::QualifyType("System.DateTime");
-
- [Ionic.Cscomp.Utilities]::QualifyType("XmlSerializer");
-
- [Ionic.Cscomp.Utilities]::QualifyType("System.Xml.XmlReader");
-
- [Ionic.Cscomp.Utilities]::QualifyType("System.This.Type.Does.Not.Exist");
-
-
- [Ionic.Cscomp.Utilities]::LoadOneAssembly("Ionic.Zip.dll");
-
- [Ionic.Cscomp.Utilities]::LoadOneAssembly("System.Xml");
-
- [Ionic.Cscomp.Utilities]::QualifyName("System.Xml");
-
-
[Ionic.Cscomp.Utilities]::GetCompletionsForNamespace("System.Collections.Generic")
-
- [Ionic.Cscomp.Utilities]::ListLoadedAssemblies();
-
-
- [Ionic.Cscomp.Utilities]::ListKnownTypes();
-
-
-
- unnecessary, because these are all built-in to the DLL
-
[Ionic.Cscomp.Utilities]::SetAssemblySearchPaths('c:\.net2.0,c:\net3.0ra,c:\.net3.5ra');
-
- [Ionic.Cscomp.Utilities]::Version();
- [Ionic.Cscomp.Utilities]::Verbose = $TRUE
-
-
-
[System.Reflection.Assembly]::LoadFrom("c:\\users\\dino\\elisp\\cscomp\\CscompUtilities.dll");
-
-
-
-*/
-
-
diff --git a/CscompUtilities.dll b/CscompUtilities.dll
deleted file mode 100644
index de1a4ba..0000000
Binary files a/CscompUtilities.dll and /dev/null differ
diff --git a/ICSharpCode.NRefactory.dll b/ICSharpCode.NRefactory.dll
deleted file mode 100644
index 0c52ab5..0000000
Binary files a/ICSharpCode.NRefactory.dll and /dev/null differ
diff --git a/aspx-mode.el b/aspx-mode.el
deleted file mode 100644
index 984e907..0000000
--- a/aspx-mode.el
+++ /dev/null
@@ -1,496 +0,0 @@
-;;; aspx-mode.el --- mode for editing ASPX files
-;;
-;; Copyright (C) 2010 Dino Chiesa
-;;
-;; Author: Dino Chiesa <dpchiesa@hotmail.com>
-;; Created: May 2010
-;; Version: 0.1
-;; Keywords: C#, languages, extensions, files
-;; URL: ???
-;;
-;; This is an emacs mode for editing single-file ASPX modules,
-;; which can contain HTML, javascript, C# or VB, and
-;; CSS code.
-;;
-;; It relies on multi-mode.
-;; (see http://www.loveshack.ukfsn.org/emacs )
-;;
-;; It provides context-sensitive fontification and indent in all of the
-;; various chunks o an ASPX file. Browser-side Javascript within script
-;; blocks gets fontified correctly. Server-side script blocks get
-;; fontified properly. CSS gets indented and fontified. And of course
-;; HTML.
-;;
-;; It relies on espresso for the javascript mode, css-mode for CSS,
-;; html-mode for HTML, and csharp-mode 0.7.5 or later for the
-;; server-side c# code.
-;;
-;; Bugs:
-;;
-;; - The fontification sort of turns on and off as you cursor through
-;; the buffer, making for a somewhat odd user experience.
-;;
-;; - the fontification sometimes doesn't happen within a chunk, til you
-;; modify the text within the chunk. There's probably a fix for
-;; this.
-;;
-;;
-;; Thu, 13 May 2010 23:44
-;;
-;; Licensed according to the Microsoft Public License (Ms-PL)
-;;
-;; This license governs use of the accompanying software. If you use
-;; the software, you accept this license. If you do not accept the
-;; license, do not use the software.
-;;
-;; 1. Definitions
-;;
-;; The terms "reproduce," "reproduction," "derivative
-;; works," and "distribution" have the same meaning here as under
-;; U.S. copyright law.
-;;
-;; A "contribution" is the original software, or any additions or
-;; changes to the software.
-;;
-;; A "contributor" is any person that distributes its contribution
-;; under this license.
-;;
-;; "Licensed patents" are a contributor's patent claims that read
-;; directly on its contribution.
-;;
-;; 2. Grant of Rights
-;;
-;; (A) Copyright Grant- Subject to the terms of this license,
-;; including the license conditions and limitations in section 3,
-;; each contributor grants you a non-exclusive, worldwide,
-;; royalty-free copyright license to reproduce its contribution,
-;; prepare derivative works of its contribution, and distribute its
-;; contribution or any derivative works that you create.
-;;
-;; (B) Patent Grant- Subject to the terms of this license, including
-;; the license conditions and limitations in section 3, each
-;; contributor grants you a non-exclusive, worldwide, royalty-free
-;; license under its licensed patents to make, have made, use, sell,
-;; offer for sale, import, and/or otherwise dispose of its
-;; contribution in the software or derivative works of the
-;; contribution in the software.
-;;
-;; 3. Conditions and Limitations
-;;
-;; (A) No Trademark License- This license does not grant you rights
-;; to use any contributors' name, logo, or trademarks.
-;;
-;; (B) If you bring a patent claim against any contributor over
-;; patents that you claim are infringed by the software, your patent
-;; license from such contributor to the software ends automatically.
-;;
-;; (C) If you distribute any portion of the software, you must
-;; retain all copyright, patent, trademark, and attribution notices
-;; that are present in the software.
-;;
-;; (D) If you distribute any portion of the software in source code
-;; form, you may do so only under this license by including a
-;; complete copy of this license with your distribution. If you
-;; distribute any portion of the software in compiled or object code
-;; form, you may only do so under a license that complies with this
-;; license.
-;;
-;; (E) The software is licensed "as-is." You bear the risk of using
-;; it. The contributors give no express warranties, guarantees or
-;; conditions. You may have additional consumer rights under your
-;; local laws which this license cannot change. To the extent
-;; permitted under your local laws, the contributors exclude the
-;; implied warranties of merchantability, fitness for a particular
-;; purpose and non-infringement.
-;;
-;;;
-
-
-(require 'multi-mode)
-(require 'csharp-mode)
-(require 'espresso "espresso.el")
-;;(require 'javascript-mode "javascript.el")
-(require 'css-mode)
-
-
-
-(defvar aspx-mode-log-level 0
- "The current log level for operatopms specific to aspx-mode.
-0 = NONE, 1 = Info, 2 = VERBOSE, 3 = DEBUG, 4 = SHUTUP ALREADY. ")
-
-
-(defun aspx-mode-log (level text &rest args)
- "Log a message at level LEVEL.
-If LEVEL is higher than `aspx-mode-log-level', the message is
-ignored. Otherwise, it is printed using `message'.
-TEXT is a format control string, and the remaining arguments ARGS
-are the string substitutions (see `format')."
- (if (<= level aspx-mode-log-level)
- (let* ((msg (apply 'format text args)))
- (message "aspx-mode: %s" msg))
- t))
-
-
-(defconst aspx-mode-server-lang-re
- "\\([Cc]#\\|[Vv][Bb]\\)"
- "Regex for matching on the ASPX langauge.")
-
-
-(defconst aspx-mode-server-script-start-re
- (concat
- "<\\(script\\|SCRIPT\\)[ \t\n\r\v\f]+"
- "\\("
- "language=[\"']"
- aspx-mode-server-lang-re
- "[\"'][ \t\n\r\v\f]+runat=[\"']server[\"']"
- "\\|"
- "runat=[\"']server[\"'][ \t\n\r\v\f]+language=[\"']"
- aspx-mode-server-lang-re
- "[\"']"
- "\\)[ \t\n\r\v\f]*>"
- )
-"Regex for matching the <script> tag that begins a block of
-ASPX server-side code. It tries to match on <script language='C#'
runat='server'...>
-as well as <script runat='server' language='C#' ...>
-" )
-
-
-(defconst aspx-mode-page-decl-re
- (concat
- "<%@"
- "[ \t\n\r\v\f]+"
- "\\(Page\\|Control\\)"
- "[ \t\n\r\v\f]+"
- )
-
- "Regex for matching the page/control declaration"
- )
-
-
-(defconst aspx-mode-browser-script-start-re
- (concat
- "<\\(script\\|SCRIPT\\)[ \t\n\r\v\f]+"
- "\\("
- "type=[\"']text/javascript[\"'][
\t\n\r\v\f]+language=[\"'][Jj]ava[Ss]cript[\"']"
- "\\|"
- "language=[\"'][Jj]ava[Ss]cript[\"'][
\t\n\r\v\f]+type=[\"']text/javascript[\"']"
- "\\|"
- "type=[\"']text/javascript[\"']"
- "\\|"
- "language=[\"'][Jj]ava[Ss]cript[\"']"
- "\\)")
-
-"Regex for matching the <script> tag that begins a block of
-browser-side javascript code. It tries to match on
-<script language='javascript' ...> or
-<script type='text/javascript' ...> or
-<script type='text/javascript' language='javascript' ...> or
-<script language='javascript' type='text/javascript' ...>
-")
-
-
-(defconst aspx-mode-css-block-start-re
- (concat
- "<\\(style\\|STYLE\\)"
- "[ \t\n\r\v\f]+"
- "type=[\"']text/css[\"']"
- "[ \t\n\r\v\f]*"
- ">")
- "Regex to match the beginning of a CSS block."
- )
-
-
-
-(defvar aspx-mode--last-chunk-result nil
- "cached result of the last chunk analysis")
-
-(defvar aspx-mode-update-interval 1
- "The amount of time in seconds after the last change before trying to
-re-fontify the current block.")
-
-(defvar aspx-mode-timer nil)
-
-
-
-
-
-;; When in multi-mode, I want espresso to indent to the
-;; <script> tag. Use advice on the espresso indentation
-;; calculation, to make that happen.
-(defadvice espresso--proper-indentation (after
- aspx-mode-advice-1
- compile activate)
- (if (and (boundp 'multi-mode)
- multi-mode)
- (if (eq ad-return-value 0)
- (setq ad-return-value (+ ad-return-value 4)))))
-
-
-
-
-;; =======================================================
-;; dinoch - Thu, 13 May 2010 23:38
-;; factored out so that I can attach advice to it.
-;; Did this for multi-mode support in ASPX files.
-;; =======================================================
-(defun css--proper-indentation ()
- (save-excursion
- (back-to-indentation)
- (let ((p (parse-partial-sexp (point-min) (point)))
- (end-brace-p (looking-at "}")))
- (cond
- ((or (nth 8 p) (looking-at "/[/*]"))
- (current-indentation))
- ((save-excursion
- (and (skip-chars-backward " \t\n:,")
- (looking-at "[:,]")))
- (save-excursion
- (css-re-search-backward "^[ \t]*\\w")
- (+ (current-indentation) css-indent-level)))
- ((nth 1 p)
- (save-excursion
- (goto-char (nth 1 p))
- (+ (current-indentation) (if end-brace-p 0 css-indent-level))))
- (t
- 0)))))
-
-
-(defun css-indent-line ()
- (interactive)
- (let ((indent (css--proper-indentation))
- (offset (- (current-column) (current-indentation))))
- (indent-line-to indent)
- (if (> offset 0) (forward-char offset))))
-
-
-
-;; Likewise with css-mode indentation.
-(defadvice css--proper-indentation (after
- aspx-mode-advice-2
- compile activate)
- (if (and (boundp 'multi-mode)
- multi-mode)
- (if (eq ad-return-value 0)
- (setq ad-return-value (+ ad-return-value 4)))))
-
-
-
-
-
-
-(defun aspx-mode-timer-elapsed ()
- (aspx-mode-log 2 "timer fired.")
- ;;(run-hooks 'aspx-mode-timer-elapsed-hook)
- (aspx-mode-refontify-current-chunk-after-idle))
-
-
-(defun aspx-mode-restart-timer ()
- (if (timerp aspx-mode-timer) (cancel-timer aspx-mode-timer))
- (setq aspx-mode-timer
- (run-with-timer aspx-mode-update-interval nil
'aspx-mode-timer-elapsed)))
-
-(defun aspx-mode-after-change-fn (begin end length)
- (aspx-mode-maybe-invalidate-cached-chunk begin end length)
- (if multi-mode (aspx-mode-restart-timer)))
-
-
-
-(defun aspx-mode-maybe-invalidate-cached-chunk (begin end old-length)
- (let ((new-length (- end begin))
- (old-end (+ begin old-length)))
-
- ;; Invalidate if the length changed (we need to recalc the chunk limits)
- ;; or if the change traversed the end of the chunk.
- (if (and aspx-mode--last-chunk-result
- (or (/= old-length new-length)
- (>= old-end (nth 2 aspx-mode--last-chunk-result))))
- (setq aspx-mode--last-chunk-result nil))))
-
-
-
-(defun aspx-mode-refontify-current-chunk-after-idle ()
- "Fontify the current (cached) chunk. This fn is called after a timer
-expires, when the buffer has sats idle for 2s.
-"
- (aspx-mode-log 2 "fontifying (%d %d)"
- (nth 1 aspx-mode--last-chunk-result)
- (nth 2 aspx-mode--last-chunk-result))
-
- (if aspx-mode--last-chunk-result
- ;; Remove text props in the chunk, to force a new fontification
- ;; later. Do this within a save-buffer-state, because we're not
- ;; *really* changing the buffer.
- (c-save-buffer-state ()
- (set-text-properties (nth 1 aspx-mode--last-chunk-result)
- (nth 2 aspx-mode--last-chunk-result)
- nil))))
-
-
-
-
-
-
-(defun aspx-mode-determine-current-chunk (pos)
- "Determine the type (mode) and limits of the chunk at POS.
-Return (MODE START END), where MODE is one of `csharp-mode',
-`javascript-mode', `html-mode', or `css-mode',
-and START and END are the limits of the chunk.
-
-Or, maybe return nil if not sure what mode it should be.
-I don't know. The doc is thin and the code is impenetrable.
-
-This method attempts to cache the calculated result and use it
-intelligently. For example if the first execution determines
-that the POS is within a C# chunk, the limits of that chunk
-are cached. If a subsequent invocation of this method provides a
-POS that is within those limits, the function can safely return
-the same chunk response, without further scanning.
-
-This works as long as the buffer hasn't changed - in other words
-it's just cursor navigation.
-"
-
- ;; If we're in the right zone, then use the cached value.
- ;; Don't use the cache if it is HTML mode, because an HTML
- ;; chunk can contain a javascript chunk, a CSS chunk, a
- ;; csharp chunk.
- (if (and aspx-mode--last-chunk-result
- (> pos (nth 1 aspx-mode--last-chunk-result))
- (< pos (nth 2 aspx-mode--last-chunk-result))
- (not (eq 'html-mode (nth 0 aspx-mode--last-chunk-result))))
- (progn
- (aspx-mode-log 3 "determine-chunk: pos %d chunk cache %s"
- pos
- (prin1-to-string aspx-mode--last-chunk-result))
- aspx-mode--last-chunk-result)
-
- (let ((mode 'html-mode)
- (start-of-block (point-min))
- (end-of-block (point-max))
- sp ep
- new-result)
-
- (save-excursion
- (save-restriction
- (widen)
- (goto-char pos)
- (cond
-
- ;; Between <script language='javascript' ..> and </script>?
- ((save-excursion
- (and (and (re-search-backward aspx-mode-browser-script-start-re
nil t)
- (setq sp (match-end 0)))
- (and (re-search-forward "</\\(script\\|SCRIPT\\)>" nil t)
- (setq ep (line-beginning-position)))
- (> ep pos)))
-
- (setq
- ;;mode 'javascript-mode
- mode 'espresso-mode
- start-of-block sp
- end-of-block (1- ep) ))
-
-
- ;; Between <style type="text/css"> and </style>?
- ((save-excursion
- (and (and (re-search-backward aspx-mode-css-block-start-re nil t)
- (setq sp (match-end 0)))
- (and (re-search-forward "</\\(style\\|style\\)>" nil t)
- (setq ep (line-beginning-position)))
- (> ep pos)))
- (setq mode 'css-mode
- start-of-block sp
- end-of-block (1- ep) ))
-
-
- ;; Between <script language='??' runat='server'> and </script>?
- ((save-excursion
- (and (and (re-search-backward aspx-mode-server-script-start-re
nil t)
- (setq sp (match-end 0)))
- (and (re-search-forward "</\\(script\\|SCRIPT\\)>" nil t)
- (setq ep (line-beginning-position)))
- (> ep pos)))
-
- ;; TODO: support VBNET-mode, too. Check the language at the
- ;; start block.
- (setq mode 'csharp-mode
- start-of-block sp
- end-of-block (1- ep) ))
-
- ;; Between <%@ Page...> and the first <html>
- ((save-excursion
- (and (and (re-search-forward "<\\(html\\|HTML\\)>" nil t)
- (setq ep (line-beginning-position)))
- (> ep pos)))
-
- ;; TODO: support VBNET-mode, too. Check the specified language at
the
- ;; start block.
- ;; This works only because csharp-mode has smarts to fontify the
- ;; @Page directive.
- (setq mode 'csharp-mode
- start-of-block 1
- end-of-block (1- ep) ))
-
-
-
- ;; ;; Between <html..> and </html>
- ;; ((save-excursion
- ;; (and (and (re-search-backward
"<\\(HTML\\|html\\)>" nil t)
- ;; (setq sp (match-beginning 0)))
- ;; (and (re-search-forward
"</\\(html\\|HTML\\)>" nil t)
- ;; (setq ep (line-end-position)))
- ;; (> ep pos)))
- ;; (setq mode 'html-mode
- ;; start-of-block sp
- ;; end-of-block (1- ep) ))
-
- (t
- nil))))
-
- ;; multi-make-list does not actually make a new list.
- ;; Instead it destructively modifies the existing list.
- ;; The doc says it wants to avoid producing a cons cell
- ;; in the post-command-hook.
- ;; Therefore, to cache the result, we need to actually
- ;; cons a distinct list. To check that the new item is
- ;; distinct, we need to compare each elt in the list.
- ;; If that's the case, start a timer.
- (setq new-result (list mode start-of-block end-of-block))
-
- (if (or (not (eq (nth 0 new-result) (nth 0
aspx-mode--last-chunk-result)))
- (not (eq (nth 1 new-result) (nth 1
aspx-mode--last-chunk-result)))
- (not (eq (nth 2 new-result) (nth 2
aspx-mode--last-chunk-result))))
- (progn
- (aspx-mode-log 3 "new chunk, restart timer")
- (aspx-mode-restart-timer)))
-
- (setq aspx-mode--last-chunk-result
- (multi-make-list mode start-of-block end-of-block))
-
- )))
-
-
-
-(defun aspx-mode ()
- "Mode for editing ASPX files with embedded C# script blocks,
-as well as CSS, Javascript, and HTML.
-"
- (interactive)
- (set (make-local-variable 'multi-mode-alist)
- ;; This is a very odd data structure. It doesn't make sense that
- ;; it is formatted this way. The documentation is completely
- ;; unhelpful.
- '(
- (csharp-mode . aspx-mode-determine-current-chunk)
- (espresso-mode . nil) ;; javascript
- (css-mode . nil)
- (html-mode . nil)
- ))
- (add-hook 'after-change-functions 'aspx-mode-after-change-fn nil t)
- (multi-mode-install-modes))
-
-
-
-
-
-(provide 'aspx-mode)
diff --git a/cscomp-base.el b/cscomp-base.el
deleted file mode 100644
index 420ff27..0000000
--- a/cscomp-base.el
+++ /dev/null
@@ -1,35 +0,0 @@
-;;; cscomp-base.el -- part of cscomp, which provides
-;;; Smart code completion for C#
-;;
-;; Author: Dino Chiesa <dpchiesa@hotmail.com>
-;; Maintainer: Dino Chiesa <dpchiesa@hotmail.com>
-;; Created: April 2010
-;; Modified: January 2011
-;; Version: 0.1.9
-;; Keywords: c# languages oop mode
-;; X-URL: http://code.google.com/p/csharpmode/
-;;
-
-
-(defcustom cscomp-log-level 1
- "The current log level for C# completion operations.
-0 = NONE, 1 = Info, 2 = VERBOSE, 3 = DEBUG. ")
-
-(defun cscomp-time ()
- "returns the time of day as a string. Used in the `cscomp-log' function."
- (substring (current-time-string) 11 19)) ;24-hr time
-
-
-(defun cscomp-log (level text &rest args)
- "Log a message at level LEVEL.
-If LEVEL is higher than `cscomp-log-level', the message is
-ignored. Otherwise, it is printed using `message'.
-TEXT is a format control string, and the remaining arguments ARGS
-are the string substitutions (see `format')."
- (if (<= level cscomp-log-level)
- (let* ((msg (apply 'format text args)))
- (message "CSCOMP %s %s" (cscomp-time) msg))))
-
-(provide 'cscomp-base)
-
-;; End of cscomp-base.el
diff --git a/csharp-analysis.el b/csharp-analysis.el
deleted file mode 100644
index ffa829f..0000000
--- a/csharp-analysis.el
+++ /dev/null
@@ -1,1533 +0,0 @@
-;;; csharp-analysis.el -- C# source code analysis in emacs
-;;
-;; Author: Dino Chiesa <dpchiesa@hotmail.com>
-;; Maintainer: Dino Chiesa <dpchiesa@hotmail.com>
-;; Created: January 2011
-;; Modified: February 2011
-;; Version: 0.2
-;; Keywords: c# languages oop mode
-;; X-URL: http://code.google.com/p/csharpmode/
-;;
-;;
-;;; Commentary:
-;;
-;; This module provides sourcecode analysis to support the cscomp
-;; (csharp-completion) module.
-;;
-;; ------------------------------------------------------------------
-;;
-;; The original csharp-completion package I wrote used the semantic
-;; package from cedet. According to the description of the semantic
-;; package, it is the perfect tool for the job. In practice, semantic is
-;; complex, opaque, and brittle. In general I find it a bloody
-;; nightmare to use. The documentation is absent or useless. Examining
-;; the code reveals that it is disordered and haphazard. In operation,
-;; it treats C# namespaces as classes, and no matter what I tried I
-;; couldn't get it to treat the namespace as an independent kind of
-;; thing. It uses cute names for various features, in lieu of names that
-;; actually convey meaning. There are many other problems. Because of
-;; all that, it took me a great effort to understand enough to make it
-;; somewhat usable for my purpose. But finally, I got there.
-;;
-;; But then! I upgraded from emacs v22 to 23.2, and semantic blew up.
-;; Even the wisent file broke. Back to square one. I have asked for
-;; support and assistance multiple times from the author and have never
-;; received a response.
-;;
-;; Rather than once again invest time in working with semantic, I've
-;; moved to the Ast magic from SharpDevelop -
-;; ICSharpCode.NRefactory.dll. The documentation for it is no better
-;; than that for Semantic, but... it works as I expect it to. It is
-;; doscoverable, and it behaves rationally. It is complete.
-;;
-;; The .NET Dll is used via the CscompShell, which is a powershell that
-;; loads the CscompUtilities.dll. One of the methods in that DLL returns
-;; an abstract syntax tree, formatted as a lisp s-expression. It
-;; constructs that s-exp using the NRefactory assembly.
-;;
-;; The way it works is to save the current buffer to a temporary file,
-;; then run the syntax analysis on that temporary file, before deleting
-;; the temp file. Then, the code running in powershell loops through all the
-;; source elements in the file, and emits a hierarchically arranged set
-;; of lisp structures representing those elements. Each element is
-;; known as a "tag", borrowing from the language of the semantic
-;; package. A tag represents a namespace. the namespace tag has
-;; children, which are "type" tags. Each type tag may have fields
-;; methods and properties as children. A method has a code block as a
-;; child. And so on.
-;;
-;; This module exports functions that do things with that abstract
-;; syntax tree - such as:
-;;
-;; - list all of the namespaces in the current buffer
-;; - list all of the types in the given namespace
-;; - list all of the methods/fields/properties for the given type
-;; - list the in-scope local variables for the current point in the buffer
-;; - return the parent tag of a given tag
-;;
-;; All of this syntax analysis is performed in support of code
-;; completion (intellisense).
-;;
-;; When the buffer changes, a flag is set that indicates that the AST is
-;; out of date. When the buffer stops changing, the analysis is run
-;; again. Each analysis takes a second or so for a 1000-line module.
-;;
-
-(require 'cscomp-base) ;; cscomp-log
-(require 'csharp-shell) ;; csharp-shell-invoke-shell-fn
-(require 'cl) ;; first, second, dolist, etc
-
-(defvar csharp-analysis-last-change-time nil
- "Time of last buffer change.")
-(make-variable-buffer-local 'csharp-analysis-last-change-time)
-
-(defvar csharp-analysis-syntax-tree nil
- "buffer-local result of the most recent syntactic analysis of
- the current buffer. It is a lisp s-expression. In general, this
- variable should not be referenced directly. Instead
- applications should call
- `csharp-analysis-get-analysis'")
-(make-variable-buffer-local 'csharp-analysis-syntax-tree)
-
-(defvar csharp-analysis-is-running nil
- "If t, source code analysis is running for the current C# buffer.")
-(make-variable-buffer-local 'csharp-analysis-is-running)
-
-(defvar csharp-analysis-no-changes-timeout 0.75
- "Time to wait after last change before starting syntax analysis. In the
-timer event, if the last change is less that this amount of time ago, then
-analysis is NOT performed. ")
-(make-variable-buffer-local 'csharp-analysis-no-changes-timeout)
-
-(defvar csharp-analysis-timer-interval 2
- "Interval in seconds for timer events. This is not the interval on
-which analysis gets performed; it's the interval on which we check to
-see if a new analysis is necessary. ")
-(make-variable-buffer-local 'csharp-analysis-timer-interval)
-
-(defvar csharp-analysis-syntax-tree-out-of-date t
- "a boolean indicating whether this module thinks the analysis
- of the sourcecode buffer is out of date. When this is true, and
- when the results of an analysis is requested via a call to
- `csharp-analysis-get-analysis', then a new analysis is
- performed.")
-(make-variable-buffer-local 'csharp-analysis-syntax-tree-out-of-date)
-
-(defvar csharp-analysis-timer nil
- "a timer object.")
-
-(defvar csharp-analysis--query-cache nil
- "an alist. For internal use of the csharp-analysis module only.")
-
-(defalias 'csharp-analysis-float-time
- (if (fboundp 'float-time)
- 'float-time
- (if (featurep 'xemacs)
- (lambda ()
- (multiple-value-bind (s0 s1 s2) (values-list (current-time))
- (+ (* (float (ash 1 16)) s0) (float s1) (* 0.0000001 s2)))))))
-
-
-(defun csharp-analysis-after-change-fn (start stop len)
- "invoked after the buffer changes. This fn simply records the
-time of the last change.
-"
- (cscomp-log 4 "after-change: recording change time")
- (setq csharp-analysis-last-change-time (csharp-analysis-float-time)))
-
-
-
-(defun csharp-analysis-after-save-fn ()
- "a fn that gets invoked after the save of a buffer. If there is a local
- variable called `csharp-analysis-is-running', then cscomp immediately
- analyzes the sourcecode in the buffer."
- (if (local-variable-p 'csharp-analysis-is-running (current-buffer))
- (progn
- ;;(setq csharp-analysis-syntax-tree-out-of-date t)
- ;;(cscomp-log 3 "after-save: marking out of date")
- ;;(csharp-analysis-analyze-buffer)
- )))
-
-(defun csharp-analysis-can-parse-file (file-name)
- "return t if the buffer is a C# source file."
- (unless (stringp file-name)
- (error "Invalid file-name"))
- (string-match "\\.cs$" file-name))
-
-
-
-(defun csharp-analysis-timer-event (buffer)
- "This fn gets called by a timer, on a regular interval. It
-marks the buffer as out of date, in other words due for
-sourcecode analysis, by setting `csharp-analysis-syntax-tree-out-of-date'
-if appropriate.
-
-A buffer is considered to be out of date when more than
-`csharp-analysis-no-changes-timeout' seconds have elapsed since the last
-change, and there have been other changes that have been made
-during that interval. This is checked by comparing the current
-time to `csharp-analysis-last-change-time', the last change time that is
-recorded in `csharp-analysis-after-change-fn'.
-
-If the timeout period has not expired since the last change,
-it indicates that the user is actively changing the buffer, eg
-typing, and so there's no sense marking the buffer out of date at
-the moment.
-
-If the user later requests a sourcecode analysis (abstract syntax
-tree, or AST) for the buffer by implicitly invoking
-`csharp-analysis-get-analysis', if the sourcecode
-analysis has previously been marked out of date, then cscomp
-computes a new analysis. If it is not marked out of date, then
-cscomp returns the existing analysis.
-
-When a buffer is initially loaded, the analysis is marked out of
-date, so that it is always calculated upon the first request for
-it.
-
-"
- (when (buffer-live-p buffer)
- (with-current-buffer buffer
- (if (and csharp-analysis-last-change-time
- (not csharp-analysis-syntax-tree-out-of-date))
- (let ((elapsed (- (csharp-analysis-float-time)
csharp-analysis-last-change-time)))
- (cscomp-log 4 "timer: elapsed since last change: %s"
- (prin1-to-string elapsed))
- ;; see if the buffer has stopped changing
- (when (> elapsed csharp-analysis-no-changes-timeout)
- (setq csharp-analysis-syntax-tree-out-of-date t)))
-
- (cscomp-log 4 "timer: no change since previous analysis.")))))
-
-
-(defun csharp-analysis-stop-timer ()
- (when csharp-analysis-timer
- (cancel-timer csharp-analysis-timer)
- (setq csharp-analysis-timer nil)))
-
-
-(defun csharp-analysis-get-analysis ()
- "Returns the s-expression representing the sourcecode analysis of the
-current buffer. If the current sourcecode analysis is out-of-date, then
-the analysis is performed anew, and that new result is returned. Several
-events can trigger the out-of-date condition: addition of a newline (\n)
-into the buffer; saving the buffer; other things. This module detects
-these events in the appropriate emacs hooks - such as after-save-hook, or
-the after-change-functions - and then sets the
-`csharp-analysis-syntax-tree-out-of-date' variable to a non-nil value.
-
-When this function is called and that variable is true, a new analysis is
-performed. This may take some time, as it requires saving the buffer
-contents to a temporary file, analyzing, then removing the file."
-
- (if (or csharp-analysis-syntax-tree-out-of-date
- (not csharp-analysis-syntax-tree))
- (csharp-analysis-analyze-buffer)
- csharp-analysis-syntax-tree))
-
-
-
-(defun csharp-analysis-create-temp-filename (file-name)
- (unless (stringp file-name)
- (error "Invalid file-name"))
- (let* ((prefix "cscomp")
- (temp-name (concat (file-name-sans-extension file-name)
- "_" prefix
- "."
- (file-name-extension file-name))))
-
- (cscomp-log 3 "create-temp-filename: orig=%s temp=%s" file-name temp-name)
- temp-name))
-
-
-(defun csharp-analysis-analyze-buffer ()
- "Actually do the analysis, by calling out to the AnalyzeSource method
-available within the CscompShell. That method calls out to the NRefactory
-library to perform the source analysis. The result is the lisp
-s-expression that describes the syntax tree of the buffer. "
-
- ;; I'm not sure if timers create a multi-thread scenario or not.
- ;; in case they do, and in case there's an analysis already running,
- ;; let's just hack it and return the existing value.
-
- (if (and csharp-analysis-is-running
- csharp-analysis-syntax-tree)
- (progn
- (cscomp-log 4 "csharp-analysis-analyze-buffer: analysis is already
running.")
- ;;;
- csharp-analysis-syntax-tree)
- (let
- ((temp-file-name (csharp-analysis-create-temp-filename
(buffer-file-name)))
- (delete-temp-file (lambda ()
- (when (file-exists-p temp-file-name)
- (delete-file temp-file-name)
- (cscomp-log 3 "deleted temp file %s" temp-file-name)))))
-
- ;; handle exceptions that occur during file creation,
- ;; saving, and analysis, via condition-case
- (condition-case exc1
- (progn
- (setq csharp-analysis-is-running t)
- ;; obtain mutex?
- (cscomp-log 1 "re-analyzing... ")
- (funcall delete-temp-file) ;; just in case it exists now
-
-
- ;; right here - maybe temporarily comment out the current
- ;; line? maybe?
-
- ;; The problem is that NRefactory *quits* its analysis when
- ;; it encounters some classes of syntax errors. which
- ;; errors? I don't know. But in the case where a person is
- ;; asking for completions "right here", sometimes NRefactory
- ;; chokes on the incomplete line of code, which the user is
- ;; asking for completions on. As a result it doesn't emit a
- ;; CompilationUnit that contains any members following that
- ;; point. If a variable gets initialized based on a field
- ;; that lies AFTER the current line in the buffer, then the
- ;; csharp-completion stuff won't work properly.
-
- ;; Just removing, or commenting out, the offending line
- ;; allows NRefactory to continue its analysis. That might be
- ;; the right thing to do here. Have to figure out
- ;; why/when/how that should be done.
-
- ;; write the buffer to the temporary file
- (write-region nil nil temp-file-name nil 7)
- (cscomp-log 3 "wrote temp file %s" temp-file-name)
- (setq csharp-analysis-syntax-tree
- (csharp-shell-invoke-shell-fn "GetAstForSourceFile"
temp-file-name))
- (funcall delete-temp-file)
-
- (setq csharp-analysis-last-change-time nil
- csharp-analysis-syntax-tree-out-of-date nil
- csharp-analysis-is-running nil
- csharp-analysis--query-cache nil) ;; clear cache
-
- ;; release mutex?
- csharp-analysis-syntax-tree)
- (progn
- (error "analysis failed.")
- (funcall delete-temp-file)
- (setq csharp-analysis-is-running nil)
- csharp-analysis-syntax-tree)))))
-
-
-;;;###autoload
-(define-minor-mode csharp-analysis-mode
- "A minor mode to do on-the-fly c# source code parsing and analysis.
-
-When this function is called interactively, it toggles the minor
-mode.
-
-With arg, turn csharp-analysis mode on if and only if arg
-is positive.
-
-When this mode is on, emacs periodically analyzes the current
-buffer and stores a representation of the abstract syntax
-tree (AST) for the C# source code. This AST is then used to
-facilitate smart code completion, something like emacs'
-autocomplete function, but smarter. See
-`cscomp-complete-at-point'.
-
-"
-
- nil nil nil
- (cond
- ;; turn the mode ON.
-
- (csharp-analysis-mode
- (if (not (csharp-analysis-can-parse-file buffer-file-name))
- (cscomp-log 2 "cscomp cannot check syntax in buffer %s" (buffer-name))
- (add-hook 'after-change-functions 'csharp-analysis-after-change-fn nil t)
- (add-hook 'after-save-hook 'csharp-analysis-after-save-fn nil t)
-
- (add-hook 'kill-buffer-hook 'csharp-analysis-stop-timer nil t)
-
- ;; set a timer to fire on an interval
- (setq csharp-analysis-timer
- (run-at-time nil csharp-analysis-timer-interval
- 'csharp-analysis-timer-event
- (current-buffer)))
-
- ;; do the first analysis?
- ;;(csharp-analysis-analyze-buffer)
-
- (cscomp-log 1 "csharp-analysis-mode: setting vars for initial
conditions");
- (setq csharp-analysis-is-running nil)))
-
- ;; turn the mode OFF.
- (t
- (remove-hook 'after-change-functions 'csharp-analysis-after-change-fn t)
- (remove-hook 'after-save-hook 'csharp-analysis-after-save-fn t)
- (remove-hook 'kill-buffer-hook 'csharp-analysis-stop-timer t)
- (csharp-analysis-stop-timer)
- (setq csharp-analysis-is-running nil))))
-
-
-;; ==================================================================
-;; ==================================================================
-
-
-
-(defun csharp-analysis-useful-taglist (ast)
- "returns the useful taglist from an AST. The first, toplevel
-AST is contains the string 'CompilationUnit as its car. This fn
-trims that, if it is present, and returns the list of children. If
-it is not present, this fn just returhs the original taglist.
-"
- (if (and
- (symbolp (first ast))
- (string= 'CompilationUnit (symbol-name (first ast))))
- (progn
- ;;(message "useful: %s" (prin1-to-string (cdadr ast)))
- (cdadr ast))
- ast))
-
-
-
-;; -------------------------------------------------------
-(defun csharp-analysis-get-toplevel-tags-from-ast (ast tag-type)
- "From the given AST, get toplevel tags of the given TAG-TYPE.
-For example, pass TAG-TYPE of \"type\" to get all the toplevel
-using clauses in an AST. This would work for an AST representing
-a namespace.
-
-This fn does not consider nested elements.
-
-Example:
- (csharp-analysis-get-toplevel-tags-from-ast myast \"type\")
-
-See also: `csharp-analysis-get-toplevel-tagnames-from-ast'.
-
-"
- (when (not tag-type) (error "tag-type must be non-nil"))
- (let ((result (list)))
- (dolist (entry (csharp-analysis-useful-taglist ast)) ;; loop over the list
- (if (and
- (consp entry)
- (symbolp (first entry))
- (string= tag-type (csharp-analysis-tag-flavor entry)))
- (setq result (cons entry result))))
- (reverse result)))
-
-
-
-(defun csharp-analysis-get-toplevel-tags (tag-type)
- "Get toplevel tags of the given TAG-TYPE from the AST for the
-current buffer. For example, pass TAG-TYPE of \"using\" to get
-all the toplevel using clauses in an AST. Does not get nested
-elements.
-
-Example:
- (csharp-analysis-get-toplevel-tags \"attribute\")
-
-See also: `csharp-analysis-get-toplevel-tagnames'.
-
-"
- (interactive "stag type: ")
- (csharp-analysis-get-toplevel-tags-from-ast (csharp-analysis-get-analysis)
tag-type))
-;; -------------------------------------------------------
-
-
-
-(defun csharp-analysis-nested-tags (node &optional include-params)
- "Get the nested tags (or nodes) for the given NODE (or tag).
-In a namespace node, nested tags would be nodes representing
-types, enumerated in an element called \"children\". In a type,
-the child nodes are also in a \"children\" node, and represent
-methods, fields, and properties. In a method, the children are
-the expressions that define the method logic, and are available
-in a node called \"block\". Within a block, an \"if\" node has
-children in \"then\" and \"else\" clauses. A \"trycatch\" node
-has children in the \"try\" clause, all \"catch\" clauses, and
-the \"finally\" clause, if any. And so on.
-
-This fn is intended to support
-`csharp-analysis-local-variables', which gets a list of local
-variables. To do that, the fn needs to know the current scope
-tree.
-
-"
- (when (not node) (return nil))
-
- (let* ((sname (symbol-name (first node)))
- (nested-tags
- (cond
- ((string= sname "if")
- (append
- (assoc 'then node)
- (csharp-analysis-get-toplevel-tags-from-ast node "elseif") ;;
there may be multiple of these
- (assoc 'else node))) ;; the else clause may be nil
-
- ((or
- (string= sname "foreach")
- (string= sname "for")
- (string= sname "block")
- (string= sname "then")
- (string= sname "else")
- (string= sname "elseif")
- (string= sname "finally")
- (string= sname "catch")
- (string= sname "try"))
- (cdr node)) ;; every child except the containing scope
-
-
- ((string= sname "trycatch")
- (append
- (csharp-analysis-get-toplevel-tags-from-ast node "try")
- (csharp-analysis-get-toplevel-tags-from-ast node "catch")
- (csharp-analysis-get-toplevel-tags-from-ast node "finally")))
-
- ((string= sname "property")
- (append
- (csharp-analysis-get-toplevel-tags-from-ast node "get") ;; may be
nil
- (csharp-analysis-get-toplevel-tags-from-ast node "set"))) ;; may
be nil
-
- (t
- (let (c)
- (setq c (assoc 'block node))
- (if c (list c)
- (setq c (assoc 'children node))
- (if c (cdr c)
- nil))))
- ;;(csharp-analysis-get-toplevel-tags-from-ast node "block")
- ;;(csharp-analysis-get-toplevel-tags-from-ast node "children")
-
- )))
-
- (if include-params
- (let ((params (cadr (assoc 'params node))))
- (if params
- (setq nested-tags (append (list params) nested-tags)))))
-
- nested-tags))
-
-
-
-
-(defun csharp-analysis-get-local-arguments-from-ast (ast)
- "From the given AST, get all the local arguments that are in scope at
-the position defined by LINE and COL in the buffer described by the AST.
-
-Within a method, this is the arguments to the method.
-
-Within a property setter, this is the value argument.
-
-Otherwise, nil.
-
-"
-
- (let ((method (or
- (csharp-analysis-get-enclosing-tag "method")
- (csharp-analysis-get-enclosing-tag "ctor")
- (csharp-analysis-get-enclosing-tag "set"))))
-
- (if method
- (csharp-analysis-method-params method))
-
- ))
-
-
-
-
-(defun csharp-analysis-local-arguments ()
- "Gets all the local arguments that are in scope in the
-current position in the buffer.
-
-This includes arguments passed to the enclosing method, if any.
-The result does not include local variables declared in the current method, or
execution
-block, or variables declared within any nested
-curly-brace scopes that are active at the current buffer position.
-
-An example output:
-
-\((var \"args\" \"System.String[]\" (location (20 29) (20 38))))
-
-This function prints its result if called interactively. This is for
-diagnostic purposes only.
-
-"
- (interactive)
- (let ((result
- (csharp-analysis-get-local-arguments-from-ast
- (csharp-analysis-useful-taglist (csharp-analysis-get-analysis)))))
- (if (called-interactively-p 'any)
- (message "result: %s" (prin1-to-string result)))
- result))
-
-
-
-
-(defun csharp-analysis-get-local-variables-from-ast (ast line col &optional
indent)
- "From the given AST, get all the local variables that are in scope at
-the position defined by LINE and COL in the buffer described by the AST.
-
-If the position is within a method, the result does not include
-method parameters. The result does include variables defined
-within the scope of the method, as well as within any active
-nested curly-brace scopes.
-
-If the position is within some other execution scope, such as a
-getter for a property, the result includes variables defined in
-that scope as well as any active nested scopes.
-
-The list excludes instance variables and method arguments that may
-be available at the given position in the buffer.
-
-See also: `csharp-analysis-local-arguments'
-
-"
- (if (not indent)
- (setq indent ""))
-
- (let ((nodes ast)
- result)
- (while nodes
- (let ((node (car nodes)))
- (if (and (consp node) (symbolp (car node)))
- (let ((flavor (symbol-name (car node)))
- (tag-name (csharp-analysis-tag-name node))
- (location (cdr (assoc 'location node))))
-
- (cscomp-log 4 "%sconsidering tag (%s %s ...)"
- indent flavor tag-name)
-
- (if (and location (csharp-analysis-location-contains-line-col
location line col))
- (progn
- (cscomp-log 4 "%sCONTAINING SCOPE" indent)
- (setq nodes nil) ;; this will be the last time through the
loop
- (if (or
- (string= flavor "foreach")
- (string= flavor "for")
- (string= flavor "using")
- (string= flavor "block")
- (string= flavor "then")
- (string= flavor "else")
- (string= flavor "elseif")
- (string= flavor "finally")
- (string= flavor "catch")
- (string= flavor "try"))
-
- (progn
- (cscomp-log 4 "%slooking for vars " indent)
-
- (let ((all-vars
- (csharp-analysis-get-toplevel-tags-from-ast
node "var"))
- inner-result)
-
- ;; include only those vars within the block that
precede the current position
- (if all-vars
- (progn
- (cscomp-log 4 "%slooking at local vars..."
indent)
-
- (while all-vars
- (let* ((one-var (car all-vars))
- (var-location (cdr (assoc 'location
one-var)))
- (var-name (cadr one-var)))
-
- (cscomp-log 4 "%sconsidering var %s ..."
indent var-name)
-
- ;; if the var decl precedes the current
location, OR
- ;; if this is a catch variable, then
include it in the list.
- (if (or
- (string= flavor "catch")
-
(csharp-analysis-location-precedes-line-col var-location line col))
- (progn
- (cscomp-log 4 "%syes" indent)
- (setq inner-result (cons one-var
inner-result)))))
-
- (setq all-vars (cdr all-vars)))
-
- (if inner-result
- (setq result (append result (reverse
inner-result)))))
-
- (cscomp-log 4 "%s no local vars" indent))))
-
- (cscomp-log 4 "%snot a var container" indent))
-
- (let ((children (csharp-analysis-nested-tags node nil)))
- (if children
- (progn
- (cscomp-log 4 "%srecursing..." indent)
- (let ((r1
(csharp-analysis-get-local-variables-from-ast children line col (concat " "
indent))))
- (if r1
- (setq result (append result r1)))))
- (cscomp-log 4 "%sno children" indent))))
-
- (cscomp-log 4 "%snot contained within" indent)
- ))))
-
- (setq nodes (cdr nodes)))
-
- (cscomp-log 3 "%sresult '%s'" indent (prin1-to-string result))
-
- result))
-
-
-
-
-
-(defun csharp-analysis-local-variables ()
- "Gets all the local variables that are in scope in the
-current position in the buffer.
-
-This includes variables declared in the current method, or execution
-block, as well as variables declared within any nested
-curly-brace scopes that are active at the current buffer position.
-
-The list excludes instance variables that may be active at the
-current point in the buffer, as well as parameters for the
-enclosing method, if any.
-
-An example output:
-
-\((var \"args\" \"System.String[]\" (location (20 29) (20 38)))
- (var \"flavor\" \"System.Int32\" (location (20 44) (20 48)))
- (var \"z\" \"System.Int32\" (location (22 13) (22 22)))
- (var \"t\" \"var\" (location (52 13) (52 46)))
- (var \"i\" \"var\" (location (53 31) (53 32))))
-
-This function prints its result if called interactively. This is for
-diagnostic purposes only.
-
-"
- (interactive)
- (cscomp-log 3 "ENTER local-variables")
- (let* ((line (line-number-at-pos))
- (col (current-column))
- (result
- (csharp-analysis-get-local-variables-from-ast
- (csharp-analysis-useful-taglist (csharp-analysis-get-analysis))
- line col)))
- (if (called-interactively-p 'any)
- (message "result: %s" (prin1-to-string result)))
- (cscomp-log 3 "local-variables: result %s" (prin1-to-string result))
- result))
-
-
-
-
-;; -------------------------------------------------------
-(defun csharp-analysis-get-toplevel-tagnames-from-ast (ast tag-type)
- "Get names of toplevel tags from the AST, of the given TAG-TYPE.
-For example, pass TAG-TYPE of \"using\" to get all the toplevel
-using clauses in an AST.
-
-Retrieving using clauses would work with an AST representing a
-compilation unit (full buffer) or a namespace.
-
-Example:
- (csharp-analysis-get-toplevel-tagnames-from-ast myast \"using\")
-
-See also: `csharp-analysis-get-toplevel-tags-from-ast'.
-
-"
- (mapcar
- 'csharp-analysis-tag-name
- (csharp-analysis-get-toplevel-tags-from-ast ast tag-type)))
-
-
-
-
-
-(defun csharp-analysis-get-toplevel-tagnames (tag-type)
- "Get the names of toplevel tags of the given TAG-TYPE, from the ast
-for the current buffer.
-
-For example, pass TAG-TYPE of \"using\" to get all the
-toplevel using clauses in an AST.
-
-Example:
- (csharp-analysis-get-toplevel-tagnames \"using\")
-
-See also: `csharp-analysis-get-toplevel-tags'.
-
-"
- (interactive "stag type: ")
- (csharp-analysis-get-toplevel-tagnames-from-ast
(csharp-analysis-get-analysis) tag-type))
-;; -------------------------------------------------------
-
-
-
-
-
-;; -------------------------------------------------------
-(defun csharp-analysis-get-tags-from-ast (ast tag-type)
- "Get tags at any level from the given AST, of the given TAG-TYPE.
-For example, pass TAG-TYPE of \"type\" to get all the types
-defined in an AST.
-
-Example:
- (csharp-analysis-get-tags-from-ast myast \"type\")
-
-"
- (when (not tag-type) (error "tag-type must be non-nil"))
-
- (let ((result (list))
- (working-ast (csharp-analysis-useful-taglist ast)))
-
- (dolist (node working-ast) ;; loop over the list
- (cond
- ;; It's possible that not all entries in the list are cons cells.
- ((consp node)
- (let ((node-flavor (first node))
- (node-name (second node))
- (children (csharp-analysis-nested-tags node t)))
-
- ;; (message "maybe: %s [%s]"
- ;; (prin1-to-string node-type)
- ;; (prin1-to-string node-name))
-
- (if (string= tag-type node-flavor)
- (setq result (cons node result)))
-
- (if (consp children)
- ;;(message "recurse")
- (setq result
- (append
- (reverse (csharp-analysis-get-tags-from-ast children
tag-type))
- result)))))
- (t nil)))
- (reverse result)))
-
-
-(defun csharp-analysis-get-tags (tag-type)
- "Get tags of the given TAG-TYPE at any level from the ast for the current
buffer.
-For example, pass TAG-TYPE of \"type\" to get all the types
-defined in a buffer.
-
-Example:
- (csharp-analysis-get-tags \"type\")
-
-"
- (interactive "stag type: ")
- (csharp-analysis-get-tags-from-ast (csharp-analysis-get-analysis) tag-type))
-;; -------------------------------------------------------
-
-
-
-
-;; -------------------------------------------------------
-(defun csharp-analysis-get-tagnames-from-ast (ast tag-type)
- "Get names of tags from the AST, of the given TAG-TYPE.
-For example, pass TAG-TYPE of \"type\" to get all the toplevel
-types declared in an AST.
-
-Example:
- (csharp-analysis-get-tagnames-from-ast myast \"type\")
-
-See also: `csharp-analysis-get-toplevel-tagnames-from-ast'.
-See also: `csharp-analysis-get-tagnames'.
-
-"
- (mapcar
- 'csharp-analysis-tag-name
- (csharp-analysis-get-tags-from-ast ast tag-type)))
-
-
-
-
-(defun csharp-analysis-get-tagnames (tag-type)
- "Get names of all the tags of the given TAG-TYPE from the ast
-for the current buffer. For example, pass TAG-TYPE of \"type\" to
-get the names of all the types declared in an AST.
-
-Example:
- (csharp-analysis-get-tagnames \"type\")
-
-You could also use this to get all the using clauses that are
-present in the buffer.
-
-See also: `csharp-analysis-get-tags'.
-
-
-"
- (interactive "stag type: ")
- (csharp-analysis-get-tagnames-from-ast (csharp-analysis-get-analysis)
tag-type))
-;; -------------------------------------------------------
-
-
-
-
-(defun csharp-analysis--find-parent-id-from-ast (taglist desired-id &optional
indent)
-"Helper fn."
-
- (when (not taglist) (return nil))
-
- (if (not indent)
- (setq indent ""))
-
- (cscomp-log 2 "%sfind-parent-id: looking for id: %d" indent desired-id)
-
- (let ((working-taglist (csharp-analysis-useful-taglist taglist)))
-
- ;; loop over the list, looking for a node with the given
- ;; name, considering only toplevel nodes.
- (dolist (node working-taglist)
- (if (consp node)
- (let ((this-flav (csharp-analysis-tag-flavor node))
- (this-name (csharp-analysis-tag-name node))
- (this-id (csharp-analysis-tag-id node)))
- (cscomp-log 2 "%sfind-parent-id: considering: (%s %s...(id %s))"
- indent this-flav (prin1-to-string this-name)
- (if (numberp this-id)
- (prin1-to-string this-id)
- "xx"))
-
- (if (numberp this-id)
- (progn
- (if (= this-id desired-id)
- (progn
- (cscomp-log 2 "%sfind-parent-id: found %s" indent
(prin1-to-string node))
- (return working-taglist)))
-
- (if (> this-id desired-id)
- ;; recurse
- (let ((children (csharp-analysis-nested-tags node t)))
- (when children
- (cscomp-log 2 "%sfind-parent-id: recurse" indent)
- (let ((r1 (csharp-analysis--find-parent-id-from-ast
- children desired-id
- (concat indent " "))))
- (cond
- ((numberp r1)
- (return r1))
- (r1
- (return (csharp-analysis-tag-id
node)))))))))))))))
-
-
-
-(defun csharp-analysis-find-parent-tag-by-id-from-ast (taglist desired-id)
- "From the list of tags TAGLIST, returns the tag which is the parent
-of the tag with id DESIRED-ID.
-
-Returns nil if the parent cannot be found.
-
-A tag represents one node in an abstract syntax table for a C#
-buffer. For example, a tag representing a using clause might
-look like this:
-
- (import \"System\" nil
- (location (19 1) (19 14)) (id 2))
-
-A tag representing a type declaration might look like this:
-
- (type \"AstRunner\"
- (modifier \"public\")
- (children ....)
- (location (37 5) (93 6)) (id 18))
-
-"
-
- (cscomp-log 3 "find-parent-id: (%d)" desired-id)
-
- (if (eq desired-id 0) ;; special-case synthetic ID numbers
- nil
- (let* ((cache-key (format "parent-tag-by-id/%d" desired-id))
- (result (cadr (assoc cache-key csharp-analysis--query-cache))))
-
- (if result
- (progn
- (cscomp-log 3 "find-parent-id: cache hit, tag %s"
- (prin1-to-string result))
- result)
-
- (let ((r1 (csharp-analysis--find-parent-id-from-ast taglist
desired-id)))
- (cond
- ((numberp r1)
- (cscomp-log 2 "find-parent-id: found %d" r1)
- (let ((r2 (csharp-analysis-find-tag-by-id-from-ast taglist r1)))
- (cscomp-log 2 "find-parent-id: tag %s" (prin1-to-string r2))
- ;; insert into cache
- (setq csharp-analysis--query-cache
- (append csharp-analysis--query-cache (list (list cache-key
r2))))
- r2))
-
- ((consp r1)
- (let* ((r2 (csharp-analysis-tag-id r1))
- (r3 (csharp-analysis-find-tag-by-id-from-ast taglist r2)))
- ;; insert into cache
- (setq csharp-analysis--query-cache
- (append csharp-analysis--query-cache (list (list cache-key
r3))))
- r3))
-
- (t nil)))))))
-
-
-
-
-
-
-(defun csharp-analysis-find-tag-by-id-from-ast (taglist desired-id)
- "From the list of tags TAGLIST, returns the tag with id DESIRED-ID.
-
-A tag represents one node in an abstract syntax table for a C#
-buffer. For example, a tag representing a using clause might
-look like this:
-
- (import \"System\" nil
- (location (19 1) (19 14)) (id 2))
-
-A tag representing a type declaration might look like this:
-
- (type \"AstRunner\"
- (modifier \"public\")
- (children ....)
- (location (37 5) (93 6)) (id 18))
-
-"
- (when (not taglist) (return nil))
-
- (let ((working-taglist (csharp-analysis-useful-taglist taglist)))
-
- ;; loop over the list, looking for a node with the given
- ;; name, considering only toplevel nodes.
- (dolist (node working-taglist)
- (if (consp node)
- (let ((this-id (csharp-analysis-tag-id node)))
- (if (numberp this-id)
- (progn
- (if (= this-id desired-id)
- (return node))
- (if (> this-id desired-id)
- ;; recurse
- (let ((children (csharp-analysis-nested-tags node t)))
- (when children
- (let ((r1 (csharp-analysis-find-tag-by-id-from-ast
children desired-id)))
- (when r1 (return r1)))))))))))))
-
-
-
-(defun csharp-analysis-find-tag-by-id (id)
- "From the AST for the given buffer, get the tag with the given ID.
-"
- (interactive "nTag #: ")
- (message "id: %d" id)
- (let ((result
- (csharp-analysis-find-tag-by-id-from-ast
(csharp-analysis-get-analysis) id)))
- (if (called-interactively-p 'any)
- ;; If called interactively, show the result at
- ;; the bottom of the screen.
- (message "result: %s" (prin1-to-string result)))
- result))
-
-
-
-(defun csharp-analysis-get-tag-parent-from-ast (taglist tag)
- "Returns the parent (container) tag of a given TAG.
-Finds the parent of a tag.
-"
- (error "not implemented"))
-
-
-
-(defun csharp-analysis-get-tag-by-name (taglist name)
- "From the list of tags TAGLIST, returns the tag with name NAME.
-The search is done breadth-first at the top-level, and then at depth.
-
-A tag represents one node in an abstract syntax table for a C#
-buffer. For example, a tag representing a using clause might
-look like this:
-
- (import \"System\" nil
- (location (19 1) (19 14)) (id 2))
-
-A tag representing a type declaration might look like this:
-
- (type \"AstRunner\"
- (modifier \"public\")
- (children ....)
- (location (37 5) (93 6)) (id 18))
-
-"
- (when (not name) (error "name must be non-nil"))
-
- (let ((working-taglist (csharp-analysis-useful-taglist taglist)))
-
- (or
- ;; loop over the list, looking for a node with the given
- ;; name, considering only toplevel nodes.
- (dolist (node working-taglist)
- (if (and (consp node)
- (stringp (second node))
- (string= (second node) name))
- (return node)))
-
- ;; loop over the list again, looking for the named node,
- ;; considering children nodes.
- (dolist (node working-taglist)
- (if (consp node)
- (let ((children (assoc 'children node))
- r1)
- (when children
- (setq r1 (csharp-analysis-get-tag-by-name (cdr children) name))
- (when r1 (return r1)))))))))
-
-
-
-(defun csharp-analysis-get-tag-by-type-and-name (taglist tag-type tag-name)
- "From TAGLIST, a list of tags, returns the tag with the given
-TAG-TYPE and TAG-NAME.
-
-A tag represents one node in an abstract syntax table for a C#
-buffer. For example, a tag representing a using clause might
-look like this:
-
- (import \"System\" nil
- (location (19 1) (19 14)) (id 2))
-
-A tag representing a type declaration might look like this:
-
- (type \"AstRunner\"
- (modifier \"public\")
- (children ....)
- (location (37 5) (93 6)) (id 18))
-
-"
- (when (and (not tag-name)
- (not tag-type))
- (error "one of tag-name or tag-type must be non-nil"))
-
- (let ((working-taglist (csharp-analysis-useful-taglist taglist)))
-
- (or
- ;; loop over the list, looking for a node with the given
- ;; name and type, considering only toplevel nodes.
- (dolist (node working-taglist)
- (if (and (consp node)
- (symbolp (nth 0 node))
- (string= tag-type (symbol-name (nth 0 node)))
- (stringp (nth 1 node))
- (string= (nth 1 node) name))
- (return node)))
-
- ;; loop over the list again, looking for a matching node,
- ;; considering children nodes.
- (dolist (node working-taglist)
- (if (consp node)
- (let ((children (assoc 'children node))
- r1)
- (when children
- (setq r1 (csharp-analysis-get-tag-by-name (cdr children) name))
- (when r1 (return r1)))))))))
-
-
-(defun csharp-analysis-location-contains-line-col (location line col)
- "returns t if the given LOCATION (which implies a start and an end)
-brackets the given LINE and COL pair.
-"
- (let* ((start-loc (car location))
- (end-loc (cadr location))
- (start-line (car start-loc))
- (start-col (cadr start-loc))
- (end-line (car end-loc))
- (end-col (cadr end-loc)))
- (or
- (and
- (< start-line line)
- (> end-line line))
- (and
- (= start-line line)
- (<= start-col col))
- (and
- (= end-line line)
- (>= end-col col)))))
-
-
-(defun csharp-analysis-location-precedes-line-col (location line col)
- "returns t if the given LOCATION ends before the given LINE and COL pair."
- (let* ((end-loc (cadr location))
- (end-line (car end-loc))
- (end-col (cadr end-loc)))
- (or
- (< end-line line)
- (and
- (= end-line line)
- (<= end-col col)))))
-
-
-
-(defun csharp-analysis-get-enclosing-tag-from-ast (ast desired-tag-type line
col namescope
- &optional diag indent)
- "From the given AST, gets the narrowest enclosing tag of the
-given DESIRED-TAG-TYPE. DESIRED-TAG-TYPE is a string, and can be
-one of type, namespace, method, ctor, foreach, trycatch, etc.
-
-\"Narrowest\" means, if searching for a DESIRED-TAG-TYPE of 'type, get
-the smallest enclosing type. If the cursor is within a
-nested (inner) class, return the tag for the inner class. If
-there is a foreach inside a foreach, return the inner foreach.
-
-LINE and COL define the position in the buffer described by AST,
-for which to find the enclosing tag.
-
-NAMESCOPE is the naming scope for the given AST. This allows this defun to be
-recursive.
-
-"
- (if (not diag)
- (setq diag "get-enclosing-tag"))
-
- (if (not indent)
- (setq indent ""))
-
- (if (not ast)
- (progn
- (message "%s: nothing to search within" diag)
- (return nil)))
-
- (cscomp-log 2 "%sENTER %s (%s)" indent diag desired-tag-type)
-
- (let ((nodes ast)
- result)
-
- ;; Loop over the list, looking for a node with start and end
- ;; locations that bracket the current location, considering only
- ;; toplevel nodes. If found, then check for children. If there are
- ;; children, push the name onto the namescope, and recurse.
- ;; children, recurse. If no children, then add the namescope to the
- ;; tag and return the tag. If the current toplevel tag does not
- ;; bracket the current location, the continue looping.
- (while (and nodes (not result))
- (let ((node (car nodes)))
- (if (and (consp node) (symbolp (first node)))
- (let ((location (cdr (assoc 'location node)))
- (flavor (symbol-name (car node)))
- (tag-name (csharp-analysis-tag-name node)))
-
- (cscomp-log 4 "%sconsidering tag (%s %s ...)"
- indent flavor tag-name)
-
-
- (if (and location (csharp-analysis-location-contains-line-col
location line col))
- (progn
- (cscomp-log 4 "%sCONTAINING SCOPE..." indent)
- (setq nodes nil) ;; terminate outer loop
-
- (let ((children (csharp-analysis-nested-tags node t))
- (matched-tag (string= desired-tag-type (symbol-name
(car node)))))
-
- (setq result
- (if children
- (let ((ns2 (if (string= namescope "")
- tag-name
- (concat namescope "." tag-name)))
- r1)
- (cscomp-log 4 "%srecursing..." indent)
-
- (setq r1
-
(csharp-analysis-get-enclosing-tag-from-ast
- children desired-tag-type line col ns2
- diag
- (concat indent " ")))
- (or r1
- (and matched-tag
- (append node (list (list 'namescope
(format "%s" namescope)))))))
-
- ;; no children
- (and matched-tag
- (append node (list (list 'namescope (format
"%s" namescope)))))))))))))
-
- (setq nodes (cdr nodes)))
-
- result))
-
-
-
-
-
-(defun csharp-analysis-get-enclosing-tag (tag-type &optional diag)
- "Gets the current tag of the provided TAG-TYPE for the current
-position in the buffer.
-
-The TAG-TYPE can be one of: type, method, namespace, etc.
-
-"
- (interactive "stag type: ")
-
- (if (not diag)
- (setq diag "get-enclosing-tag"))
-
- (cscomp-log 3 "%s (%s)" diag tag-type)
-
- (let* ((line (line-number-at-pos))
- (col (current-column))
- (cache-key (format "enclosing-tag/%s-%d-%d" tag-type line col))
- (result (cadr (assoc cache-key csharp-analysis--query-cache))))
-
- (if result
- (cscomp-log 3 "%s cache hit" diag)
- (let ((nodes (csharp-analysis-useful-taglist
(csharp-analysis-get-analysis))))
- (setq result
- (csharp-analysis-get-enclosing-tag-from-ast nodes tag-type line
col "" diag))
- ;; insert into the cache
- (setq csharp-analysis--query-cache
- (append csharp-analysis--query-cache (list (list cache-key
result))))))
-
-
- (if (called-interactively-p 'any)
- (progn
- ;; If called interactively, show the result at
- ;; the bottom of the screen.
- (message "result: %s" (prin1-to-string result))
- (if result
- (message "result: %s (%s)"
- (csharp-analysis-tag-name result)
- (csharp-analysis-tag-flavor result)))))
- (cscomp-log 3 "%s: %s" diag (prin1-to-string result))
- result))
-
-
-
-(defun csharp-analysis-instance-variables ()
- "Return the list of instance variables (fields or properties)
-that are in scope.
-
-The return value is a list of nodes from the abstract syntax
-tree, with any hierarchy flattened. The list looks like:
-
- ((field \"_index\" \"System.Int32\" (modifier private) (location (14 9) (14
28)) (id 5))
- (field \"_Value\" \"System.Int32\" (modifier private) (location (78 9) (78
28)) (id 47))
- (property \"Verbose\" \"System.Boolean\" (modifier public) (get) (set)
(location (9 9) (12 10)) (id 4))
- (property \"Value\" \"System.Int32\" (modifier public) (get ...) (set ...)
(location (79 9) (92 10)) (id 57))
- (property \"Seven\" \"System.Int32\" (modifier public) (get) (set (modifier
private)) (location (94 9) (98 10)) (id 58)))
-
-see also: `csharp-analysis-local-variables'
-
-"
- (interactive)
- (let* ((class (csharp-analysis-get-enclosing-tag 'type))
- (children (cdr (assoc 'children class)))
- (all-vars
- (append
- (csharp-analysis-get-toplevel-tags-from-ast children "field")
- (csharp-analysis-get-toplevel-tags-from-ast children "property"))))
-
- (cscomp-log 3 "instance-variables: found instance vars: '%s'" all-vars)
- (if (called-interactively-p 'any)
- (message "result: %s"
- (mapcar
- '(lambda (item) (list (car item) (cadr item) (caddr item)))
- all-vars)))
- all-vars))
-
-
-(defun csharp-analysis-instance-members ()
- "Return the list of instance members in scope, in a C# module.
-Members include constructors, properties, fields, and methods.
-
-The return value is a list of AST nodes. It looks like:
-
-\( (ctor \"falafel\" (modifier \"public\") (params nil)
- (block (location (7 27) (7 29)))
- (location (7 16) (7 29)) (id 18))
- (property \"Verbose\" \"System.Boolean\" (modifier public) (location (8 9)
(8 28)) (id 29))
- (field \"_index\" \"System.Int32\" (modifier \"private\") (location (13 9)
(13 28)) (id 32))
- (method \"Method1\" \"System.Void\" (modifier \"public\") (params (var
\"args\" \"System.String[]\"))
- (block ... (location (16 9) (44 10)))
- (location (15 9) (44 10))
- (id 51)))
-
-"
- (csharp-analysis-class-members))
-
-
-
-;; ;;
-;; ;; Examples
-;; ;;
-;;
-;; (message "toplevel usings: %s"
-;; (prin1-to-string
-;; (csharp-analysis-get-toplevel-tagnames "using")))
-;;
-;; ;; expect nil
-;; (message "toplevel types: %s"
-;; (prin1-to-string
-;; (csharp-analysis-get-toplevel-tagnames "type")))
-;;
-;; (message "all usings: %s"
-;; (prin1-to-string
-;; (cscomp-get-tagnames-from-ast ralph "using")))
-;;
-;; (message "namespaces: %s"
-;; (prin1-to-string
-;; (csharp-analysis-get-toplevel-tagnames "namespace")))
-;;
-;; (message "namespaces: %s"
-;; (prin1-to-string
-;; (csharp-analysis-get-toplevel-tags "namespace")))
-;;
-;; (message "one namespace: %s"
-;; (prin1-to-string
-;; (csharp-analysis-get-toplevel-tag "namespace"
"Ionic.ToolsAndTests")))
-;;
-;; (message "types (all): %s"
-;; (prin1-to-string
-;; (cscomp-get-tags "type")))
-;;
-;; (message "names of types (all): %s"
-;; (prin1-to-string
-;; (cscomp-get-tagnames "type")))
-;;
-;;
-;; ;; expected: nil
-;; ;; there is no type element at the top level
-;; (message "one type: %s"
-;; (prin1-to-string
-;; (csharp-analysis-get-toplevel-tag "type" "AstSexpression")))
-;;
-;;
-;;
-;; (message "named type: %s"
-;; (prin1-to-string
-;; (cscomp-get-tag-by-name (cscomp-get-tags "type") "AstRunner")))
-;; (message "named type: %s"
-;; (prin1-to-string
-;; (cscomp-get-tag-by-name ralph "AstRunner")))
-;;
-;;
-;; (message "named field: %s"
-;; (prin1-to-string
-;; (cscomp-get-tag-by-name (cscomp-get-tags "field") "depth")))
-;;
-;;
-;; (message "methods: %s"
-;; (prin1-to-string
-;; (csharp-analysis-get-toplevel-tagnames
-;; (first
-;; (cscomp-get-tags
-;; (first
-;; (csharp-analysis-get-toplevel-tags "namespace"))
-;; "type"))
-;; "method" )))
-;;
-;;
-;; (message "fields: %s"
-;; (prin1-to-string
-;; (csharp-analysis-get-toplevel-tagnames
-;; (first ;; use the first type defined
in the file
-;; (csharp-analysis-get-toplevel-tags ;; get all types
-;; (first
-;; (csharp-analysis-get-toplevel-tags "namespace"))
-;; "type"))
-;; "field" )))
-;;
-;; (message "my type: %s"
-;; (prin1-to-string
-;; (cscomp-get-tag-from-ast
-;; (first (csharp-analysis-get-toplevel-tags "namespace"))
-;; "type" "AstRunner")))
-;;
-;; (message "one method: %s"
-;; (prin1-to-string
-;; (cscomp-get-tag-from-ast
-;; (csharp-analysis-get-toplevel-tags "namespace")
-;; "method" "Run")))
-;;
-;;
-;; (message "one field: %s"
-;; (prin1-to-string
-;; (cscomp-get-tag
-;; (cscomp-get-tags
-;; (first ;; use the first type defined
in the file
-;; (csharp-analysis-get-toplevel-tags ;; get all types
-;; (first
-;; (csharp-analysis-get-toplevel-tags "namespace"))
-;; "type"))
-;; "field" )
-;; "field" "depth")))
-
-
-
-;; (dolist (entry ralph) ;; loop over the list
-;; (cond
-;; ((consp entry)
-;; (case (first entry) ;; get the car of the entry
-;; (allocate (plot-allocation (second entry)))
-;; (free (plot-free (second entry)))))
-;; (t
-;; (message "entry: %s" entry))))
-;;
-;;
-;;
-
-(defun csharp-analysis-tag-name (tag)
- "get the name from the given TAG. The result is a string, the name
-of the method, class, property, field, or whatever."
- (when (not tag) (error "no tag available."))
- (when (not (consp tag)) (error "csharp-analysis-tag-name: the tag provided
is not valid."))
- (if (stringp (nth 1 tag))
- (nth 1 tag)
- "--"))
-
-(defun csharp-analysis-tag-flavor (tag)
- "get the flavor of the given TAG. The result is a string like
-ctor, method, property, field, namespace, and so on."
- (when (not tag) (error "no tag available."))
- (when (not (consp tag)) (error "csharp-analysis-tag-flavor: the tag provided
is not valid."))
- (symbol-name (nth 0 tag)))
-
-
-(defun csharp-analysis-tag-type (tag)
- "get the type of the given TAG. The result is a string like
-System.Int32, bool, and so on."
- (and (stringp (nth 2 tag))
- (nth 2 tag)))
-
-(defun csharp-analysis-tag-modifiers (tag)
- "get the modifier clause attached to the given TAG, if any. The
-result is a string like \"public static\" or \"private\". The result
-is nil if there is no modifier.
-"
- (nth 1 (assoc 'modifier tag)))
-
-(defun csharp-analysis-tag-location (tag)
- "get the location clause attached to the given TAG, if any. The
-result is a list like \(location (START-LINE . START-COL) (END-LINE .
END-COL)) .
-The result is nil if there is no modifier.
-"
- (assoc 'location tag))
-
-
-(defun csharp-analysis-tag-id (tag)
- "get the id attached to the given TAG, if any. The
-result is an integer, or nil.
-
-"
- (nth 1 (assoc 'id tag)))
-
-
-
-(defun csharp-analysis-method-params (tag)
- "get the parameters attached to the given TAG, if any. The tag
-must be a method to get a meaningful result. The result is a
-list describing the parameters for the method, with each entry a
-list of (NAME TYPE). The result is nil if there are no parameters, or
-if the tag is not a method.
-"
- (cdr (assoc 'params tag)))
-
-
-(defun csharp-analysis-current-class ()
- "Gets the tag for the class containing point.
-"
- (csharp-analysis-get-enclosing-tag 'type "current-class"))
-
-
-(defun csharp-analysis-class-members (tag)
- "Gets the members of the class described by the TAG.
-If TAG is nil, then this function gets the narrowest type
-containing point, and gets all the members of that.
-
-"
- (if (null tag) (setq tag (csharp-analysis-current-class)))
- (if (string= (csharp-analysis-tag-flavor tag) "type")
- (cdr (assoc 'children tag))
- nil))
-
-
-(provide 'csharp-analysis)
-
-;;; end of csharp-analysis.el
diff --git a/csharp-completion.el b/csharp-completion.el
deleted file mode 100644
index 464758c..0000000
--- a/csharp-completion.el
+++ /dev/null
@@ -1,2902 +0,0 @@
-;;; csharp-completion.el -- Smart code completion for C#
-;;
-;; Author: Dino Chiesa <dpchiesa@hotmail.com>
-;; Maintainer: Dino Chiesa <dpchiesa@hotmail.com>
-;; Created: April 2010
-;; Modified: January 2011
-;; Version: 0.2
-;; Keywords: c# languages oop mode
-;; X-URL: http://code.google.com/p/csharpmode/
-;;
-;;
-;;; Commentary:
-;;
-;; Purpose
-;;
-;; This is a package that performs code-completion or "intellisense"
-;; for C# within emacs buffers. It works on GNU Emacs running on
-;; Windows and relies on Windows PowerShell in order to work.
-;;
-;; Out of Scope
-;;
-;; This module does not do font-lock, indenting, compiling, flymake,
-;; or imenu. These C# things are provided by csharp-mode.el , which
-;; is a pre-requisite for this module.
-;;
-;; This module also does not do type-ahead completion, debugging,
-;; profiling, or management of C# project files. Those are not
-;; available anywhere, as far as I know.
-;;
-;;
-;;
-----------------------------------------------------------------------------
-;;
-;; Packaging:
-;;
-;; csharp-completion is delivered as a set of files:
-;;
-;; CscompUtilities.dll - a .NET assembly that performs work in
-;; support of code completion. For example it can enumerate the
-;; set of types in a namespace imported by a using
-;; statement. It can also perform type inference of var types,
-;; aiding in completion for such types. Return values are
-;; delivered in the form of lisp s-expressions. The DLL is
-;; implemented in C#, and is provided with this source code,
-;; licensed under the same terms.
-;;
-;; cscomp-base.el - base function, provides cscomp-log function,
-;; which is used by all other elisp modules in this
-;; package. cscomp-log is useful primarily for diagnostic
-;; purposes.
-;;
-;; csharp-shell.el - runs the Powershell that loads
-;; CscompUtilities.dll and manages input to and output from the
-;; shell.
-;;
-;; csharp-analysis.el - provides code analysis functions, for
-;; example the ability to enumerate all the methods in the type
-;; being defined in the current buffer; or to enumerate all the
-;; local variables that are in scope at a given point in a
-;; source code file.
-;;
-;; csharp-completion.el - this module, which provides executive
-;; management of the code-completion function. It provides the
-;; two main elisp defuns that perform code completion, as well
-;; as supporting functions for doing things like parsing the
-;; local code fragment in the buffer to determine what is being
-;; requested, popping up menus containing the list of completions,
-;; and so on.
-;;
-;;
-----------------------------------------------------------------------------
-;;
-;; External Dependencies
-;;
-;; ICSharpCode.NRefactory.dll -
-;; a .NET assembly that provides sourcecode-analysis capabilities,
-;; shipped as part of SharpDevelop. This DLL is used by
-;; CsCompUtilities.dll to do syntax analysis.
-;;
-;; Windows XP, Vista, or 7
-;;
-;; PowerShell 2.0 - this is included in Windows 7, free download
-;; for prior versions of Windows.
-;;
-;; GNU Emacs v23.2 or later
-;;
-;; cc-mode 5.31.? or later - included in Emacs 23.2
-;;
-;; (optionally) yasnippet, for snippet insertion. If emacs has
-;; yasnippet loaded, then this completion module will insert
-;; a snippet (template) when the user selects a Method from the
-;; completion list menu. The method snippet will have all the
-;; method parameters as placeholders; the developer then types over
-;; those placeholders to supply the actual method parameters.
-;; If yasnippet is not loaded, then the completion is just
-;; the method name, and the developer has to fill in the
-;; param-list himself. I highly recommend ya-snippet.
-;;
-;;
-----------------------------------------------------------------------------
-;;
-;; Set up
-;;
-;; To set up csharp-completion:
-;;
-;; 1. put all the elisp files into a directory, and put that
-;; directory on your load path.
-;;
-;; 2. put this in your .emacs:
-;;
-;; (eval-after-load "csharp-completion"
-;; '(progn
-;; (setq cscomp-assembly-search-paths
-;; (list "c:\\.net3.5ra" ;; <<- locations of reference
assemblies
-;; "c:\\.net3.0ra" ;; <<-
-;; ... ;; <<- other assembly directories you
use
-;; "c:\\.net2.0" ;; <<- location of .NET Framework
assemblies
-;; "c:\\.net3.5" ;; <<- ditto
-;; ))))
-;;
-;; The `cscomp-assembly-search-paths' should hold a list of
-;; directories to search for assemblies that get referenced via using
-;; clauses in the modules you edit. This will try default to
-;; something reasonable, including the "typical" .NET 2.0 and 3.5
-;; directories, as well as the default locations for reference
-;; assemblies. If you have non-default locations for these things,
-;; you should set them here. Also, if you have other libraries (for
-;; example, the WCF Rest Starter kit, or the Windows Automation
-;; assemblies) that you reference within your code, you can include
-;; the appropriate directory in this list.
-;;
-;; 3. put this into your csharp-mode-hook:
-;;
-;; ;; C# code completion
-;; (require 'csharp-completion)
-;; (csharp-analysis-mode 1)
-;; (local-set-key "\M-\\" 'cscomp-complete-at-point)
-;; (local-set-key "\M-\." 'cscomp-complete-at-point-menu)
-;;
-;;
-;;
-;;
-----------------------------------------------------------------------------
-;;
-;; Usage
-;;
-;; To use code completion, open a buffer on a C# source file. Place
-;; the cursor after a partially-completed statement, and invoke
-;; `cscomp-complete-at-point'. (Normally you would bind that fn to a
-;; particular keystroke, like M-. or M-\.) Uppn invoking that fn,
-;; this module will insert the first completion that matches. If
-;; multiple completions are possible, calling the completion function
-;; again (or pressing the bound key again) will cycle through the
-;; possibilities, similar to the way dabbrev-mode works.
-;;
-;; You can alternatively call `cscomp-complete-at-point-menu', to get
-;; a popup menu of the completion choices.
-;;
-;;
-----------------------------------------------------------------------------
-;;
-;; How it Works
-;;
-;; There are 2 complementary sources of information used to generate the
-;; completion options: introspection into compiled .NET class libraries
-;; (like the base class library), and source code analysis of the
-;; currently-being-edited buffer. Both sources are facilitated by an
-;; inferior powershell shell running within emacs. The csharp-completion
-;; module will start a powershell if it is not already running, then load
-;; into that powershell instance a custom library called CscompUtilities.
-;; (The powershell instance with the custom library loaded into it, is
-;; referred to as the CscompShell within this module.)
-;;
-;; An example: if you ask for completions on the fragment "System.D",
-;; this elisp module will then call into the CscompUtilities library,
-;; by sending a command-line to the CscompShell that invokes a static
-;; method on the library, to ask the library for possible completions
-;; on the fragment. The library builds a list of all available types
-;; from the set of referenced assemblies. It then searches the list
-;; of types to find all possible completions for the given fragment,
-;; and prints the search result, as a string formatted as a lisp
-;; s-expression, on its output. This elisp module then gathers the
-;; s-expression and evals it, resulting in a structure containing
-;; completion options for the given fragment.
-;;
-;; In this example, starting from "System.D", the list of options
-;; returned will include the namespace System.Diagnostics as well as
-;; the type System.DateTime; this module will offer those and the
-;; other options as possible completions.
-;;
-;; The latter source of information - source code analysis of the
-;; currently-being-edited buffer - is generated via the NRefactory
-;; library, which ships as part of the open-source SharpDevelop tool.
-;;
-;; In the typical case, this module uses both of those sources of
-;; information, together, to generate suggestions for completions.
-;;
-;; To illustrate how, consider another example: suppose your code has
-;; a local variable of type System.Xml.XmlDocument, named doc.
-;; Suppose the user asks for completion on the fragment "doc.L",
-;; implying that the user wants to reference a property, method or
-;; field on the doc variable, that begins with the letter L. The
-;; module uses the source code analysis to identify the name and type
-;; of the local variable. It then sends a "GetTypeInfo" command to
-;; the CscompShell, passing System.Xml.XmlDocument. The CscompShell
-;; returns a lisp s-expression enumerating the fields, methods and
-;; properties for that type. This module then filters the
-;; s-expression for members that begin with L, and this filtered list
-;; is then used to populate the completion list, which is either
-;; displayed in a popup menu, or used to cycle the completion
-;; possibilities. The list includes LastChild, LoadXml, the four
-;; Load() overloads and LocalName.
-;;
-;;
-;;
-----------------------------------------------------------------------------
-;;
-;; Here's a summary of the situations in which this module can offer
-;; completions:
-;;
-;; a. names of local variables, instance variables, and method arguments.
-;;
-;; int lengthOfList;
-;; void Method1(String lengthyArgumentName)
-;; {
-;; leng?
-;; }
-;;
-;; b. Methods, fields and properties (m/f/p) on a local variable
-;; with known type, on method arguments of known type, or on
-;; instance variables of known type:
-;;
-;; String x = "this is a string";
-;; x.?
-;;
-;; c. M/f/p on local variables with var type:
-;;
-;; var x = "this is a string";
-;; x.?
-;;
-;; d. M/f/p on local variable declarations with dependencies on var types:
-;;
-;; var s = "This is a string";
-;; var length = s.Length;
-;; var radix = length.?
-;;
-;; e. M/f/p on local variables that are initialized
-;; from instance methods and variables.
-;;
-;; void method1()
-;; {
-;; var length = this.InstanceMethod();
-;; length.?
-;; }
-;;
-;; f. M/f/p on generic types:
-;;
-;; var x = new List<String>();
-;; x.?
-;;
-;; g. constructor completion, provide template when completing
-;;
-;; var x = new System.String(?
-;;
-;; h. constructor completion as above, with unqualified type.
-;; This mode does a search in the namespaces from using clauses.
-;;
-;; var x = new TimeSpan(?
-;;
-;; i. finding types and namespaces:
-;;
-;; var x = new TimeS?
-;;
-;; j. complete static methods on known types,
-;; whether fully qualified or unqualified.
-;;
-;; String.Jo?
-;;
-;; k. present template fpr static methods on known types,
-;; whether fully qualified or unqualified.
-;;
-;; String.Join(?
-;;
-;; l. Immediate values.
-;;
-;; 7.C?
-;;
-;; m. other compound Expressions:
-;;
-;; Path.GetRandomFileName().Normalize().?
-;;
-;;
-----------------------------------------------------------------------------
-;;
-;; things that need to be tested or fixed:
-;;
-;; return new XmlS?
-;;
-;; The module does not do completion on anonymous (var) types in
-;; for loops.
-;;
-;; detection of presence of ya-snippet.el - how to correctly and
-;; dynamically check if ya-snippet is available, and load it if
-;; necessary?
-;;
-;;
-----------------------------------------------------------------------------
-;;
-;;
-;; Known bugs/problems :
-;;
-;;
-;; TODO :
-;;
-;; make an installer.
-;;
-;; Please send any comments, bugs, enhancements, or suggestions or
-;; requests for upgrades to Dino Chiesa (dpchiesa@hotmail.com)
-;;
-
-(require 'cscomp-base) ;; cscomp-log, etc. basic stuff.
-(require 'csharp-shell) ;; for CscompShell, which does code introspection
-(require 'csharp-analysis) ;; for csharp-analysis-* fns
-
-
-(defvar cscomp-current-p1 nil
- "The first part (before any dot) of the current completion.
-This is used to determine if re-using previous results is ok.
-See also `cscomp-current-list'. ")
-(defvar cscomp-current-p2 nil
- "The second part (after any dot) of the current completion.
-This is used to determine if re-using previous results is ok.
-See also `cscomp-current-list'. ")
-(defvar cscomp-current-flavor nil
- "The second part (after any dot) of the current completion.
-This is used to determine if re-using previous results is ok.
-See also `cscomp-current-list'. ")
-
-(defvar cscomp-current-list nil
- "The list of all the completions for the current request. Each
-element of the list is either a string, or a list, in which the car
-is the possible completion, and the cadr is an additional
-information about this completion.")
-
-(defvar cscomp-current-list-index nil
- "An index to an element in cscomp-current-list. This is used to
-cycle the list.")
-
-(defvar cscomp-current-fragment nil
- "The current fragment we're trying to complete. This is used to
- trim the thing that gets inserted.")
-
-(defvar cscomp-current-beginning (make-marker)
- "The beginning of the region where the last completion was inserted.")
-
-(defvar cscomp-current-end (make-marker)
- "The end of the region where the last completion was inserted.")
-
-(defvar cscomp-typeinfo-cache nil)
-
-(defcustom cscomp-typeinfo-cache-size 150
- "The max size of completion buffer cache, in entries."
- :group 'cscomp
- :type 'integer)
-
-(defcustom cscomp-assembly-search-paths nil
- "a list of strings, each one a directory in which to search for assemblies."
- :group 'cscomp
- :type 'list)
-
-(defconst cscomp--new-regexp
- "^\\([ \t\n\r\f\v]*new[ \t\n\r\f\v]+\\)\\(.+\\)$")
-
-
-(defun cscomp-referenced-assemblies ()
- "Return the list of .NET namespaces, each encoded as a string,
-referenced in the current buffer via using statements. The result
-is something like this:
-
- (\"System\" \"System.Collections\" \"System.Collections.Generic\"
\"System.Reflection\")
-
-"
- (interactive)
- (let ((result
- (csharp-analysis-get-tagnames "import")))
- (if (called-interactively-p 'any)
- (message "result: %s" (prin1-to-string result)))
- result))
-
-
-
-(defun cscomp--capitalize (word)
- "Capitalize WORD in place, and return it."
- (let ((first-char (aref word 0))
- result)
- (if (> first-char 96)
- (format "%c%s" (- first-char 32) (substring word 1))
- word)))
-
-
-
-(defun cscomp--find-matching-tags (name-fragment nodeset &optional local)
- "Return the list of tags from a given set, that
-match NAME-FRAGMENT. This is used by `cscomp-matching-local-vars',
-`cscomp-matching-instance-vars', and
-`cscomp-matching-instance-members'.
-
-"
- (let ((var-label (if local "(Variable) " "(Field/Prop) " ))
- result)
-
- (if nodeset
- (progn
- (while nodeset
- (let ((tag (car nodeset)))
- (if tag
- (let
- ((member-name (csharp-analysis-tag-name tag))
- (member-type (csharp-analysis-tag-type tag))
- (member-flavor (csharp-analysis-tag-flavor tag)))
-
- (if (eq 0 (string-match name-fragment member-name))
- (let ((descrip
- (cond
- ((string= member-flavor "var")
- (concat var-label member-type))
-
- ((or (string= member-flavor "property")
- (string= member-flavor "field"))
- (concat "(" (cscomp--capitalize member-flavor) ") "
member-type))
-
- ((string= member-flavor "method")
- (let* ((arglist (csharp-analysis-method-params tag))
- (modifiers (csharp-analysis-tag-modifiers
tag))
- (arg-descrip
- (if (> (length arglist) 0)
- (concat "("
- (mapconcat
- '(lambda (x) (concat (caddr x)
- " "
- (cadr x)))
- arglist ", ")
- ")")
- "()")))
-
- (concat "(Method) "
- " " modifiers
- " " arg-descrip
- " returns "
- member-type)))
-
- (t ""))))
-
- (cscomp-log 2 "tags: found %s (%s)"
- member-name member-type)
-
- (setq result (cons (list member-name descrip) result)))))))
- (setq nodeset (cdr nodeset)))
- (cscomp-sort-completion-list result))
- nil)))
-
-
-(defun cscomp-matching-instance-vars (name-fragment)
- "Return the list of instance variables in scope, that
-match NAME-FRAGMENT. See also, `cscomp-matching-local-vars'.
-
-"
- (interactive "sName fragment: ")
- (let ((result
- (cscomp--find-matching-tags name-fragment
(csharp-analysis-instance-variables))))
- (if (called-interactively-p 'any)
- (message "result: %s" (prin1-to-string result)))
- result))
-
-
-
-
-(defun cscomp-matching-instance-members (name-fragment)
- "Return the list of instance memebrs in scope in a C# module, that
-match NAME-FRAGMENT.
-
-See also, `cscomp-matching-local-vars',
-`cscomp-matching-instance-vars'.
-
-"
- (interactive "sName fragment: ")
- (let ((result
- (cscomp--find-matching-tags name-fragment
(csharp-analysis-instance-members))))
- (if (called-interactively-p 'any)
- (message "result: %s" (prin1-to-string result)))
- result))
-
-
-
-(defun cscomp-matching-local-vars (name-fragment)
- "Find the local variables currently in scope that match the given
-NAME-FRAGMENT.
-
-For the purposes of this fn, the set of \"local variables\"
-includes any parameters for the method, ctor, or setter block.
-
-See also, `cscomp-matching-instance-members',
-`cscomp-matching-instance-vars'.
-
-"
- (interactive "sName fragment: ")
-
- (let* ((all-vars
- (append (csharp-analysis-local-variables) ;; maybe nil
- (csharp-analysis-local-arguments))) ;; maybe nil
- (result
- (cscomp--find-matching-tags name-fragment all-vars t)))
- (if (called-interactively-p 'any)
- (message "result: %s" (prin1-to-string result)))
- result))
-
-
-(defun cscomp-type-exists (typename)
- "Determines if the type named by TYPENAME is known by the
-CscompShell. You can provide a short type name, or a
-fully-qualified name. The CscompShell must have previously
-loaded the containing assembly, for it to be known. See
-`cscomp-load-one-assembly'.
-"
- (interactive "sType name: ")
- (csharp-shell-invoke-shell-fn "QualifyType" typename))
-
-
-
-(defun cscomp-produce-csharp-arglist-block-from-tag (arglist)
- "Produces an argument list block, suitable for framing within
-parens in a method declaration, from ARGLIST, a list of local
-arguments obtained from
-`csharp-analysis-local-arguments'.
-
-When the format of ARGLIST is like this:
-
- ((var \"x\" \"System.Int32\" (location (16 29) (16 33)) (id 6))
- (var \"enabled\" \"System.Boolean\" (location (16 36) (16 41)) (id 7)))
-
-The return value is like this:
-
- int count, string melvin
-
-When the arglist is empty, the return value is a string of zero length.
-
-"
- (let ((fragment ""))
- (while arglist
- (let* ((x (car arglist))
- (var-name (cadr x))
- (var-type (caddr x)))
-
- (setq fragment (concat fragment var-type " " var-name)
- arglist (cdr arglist))
- (if arglist
- (setq fragment (concat fragment ", ")))))
- fragment))
-
-
-
-
-(defun cscomp-produce-instance-member-code-fragment (member-list)
-
-"Generate a fragment of C# source code that can be compiled to
-produce IL, which can then be inspected to determine the type of
-the var for which the user is asking completion.
-
-This fn generates dummy code that includes placeholders for all
-instance members, method arguments, and local variables. The
-generated code is then compiled, so that Cscomp can inspect the
-resulting IL to determine the type of a local var on which the
-user is asking for completion.
-
-Cscomp uses the compiler to determine the type of the var. It
-dynamically generates and compiles a class with the same variable
-declaration as the code being edited.
-
-The initialization of the var may depend on instance members. If
-so, the compiled class must provide instance members of the
-correct type to satisfy those dependencies. This function
-generates C# code to provide those instance members.
-
-For input that looks like this:
-
- ((var \"staticField1\" \"System.Int32\"
- (modifier \"private static\")
- (location (14 9) (14 20)) (id 17))
-
- (method \"InstanceMethod1\" \"System.String\"
- (modifier \"public\")
- (params
- (var \"x\" \"System.Int32\" (location (16 29) (16 33)) (id 6))
- (var \"enabled\" \"System.Boolean\" (location (16 36) (16 41)) (id 7)))
- (block ...)
- (location (16 9) (18 10)) (id 9))
- ...
- )
-
-The output will look like this:
-
- class foo {
- private static int staticField1 = default(int);
- string InstanceMethod1(...) { return default(string); }
- ...
- }
-
-Any void methods will not be emitted because they cannot affect the
-types of local variables declared in methods.
-
-"
- (let ((synthetic-code ""))
-
- (while member-list
- (let* ((x (car member-list))
- (member-name (csharp-analysis-tag-name x))
- (member-flavor (csharp-analysis-tag-flavor x))
- (member-type (csharp-analysis-tag-type x))
- (member-modifiers (csharp-analysis-tag-modifiers x))
- one-frag )
-
- (setq one-frag
- (cond
-
- ((or
- (string= member-type "void") ;; the member is a void type
- (string= member-type "System.Void"))
- "") ;; emit nothing, don't need it.
-
- ;; if it turns out I was wrong, and the fn is necessary,
- ;; we can just emit an empty fn.
-
- ((string= member-flavor "method") ;; it's a method
- (concat member-modifiers " " member-type " "
- member-name "("
(cscomp-produce-csharp-arglist-block-from-tag
- (csharp-analysis-method-params x))
- ") {"
- (if member-type
- (concat
- " return default("
- member-type
- ");")
- "")
- "} "))
-
- ((or
- (string= member-flavor "field") ;; it's an instance field
- (string= member-flavor "property")) ;; it's an instance
property
-
- (concat
- member-modifiers " " member-type " "
- member-name " = default(" member-type "); "))
-
- (t
- "")))
-
- (setq synthetic-code (concat synthetic-code one-frag)))
- (setq member-list (cdr member-list)))
- synthetic-code))
-
-
-(defun cscomp-consolidate-whitespace (s)
- "Collapse consecutive whitespace characters in the given string S
-to a single space.
-"
- ;; trim leading spaces
- (if (string-match "^\\([ \t\n\r\f\v]+\\)" s)
- (setq s (substring s (match-end 1))))
-
- ;; collapse multiple whitespace into one
- (while (string-match "\\([ \t\n\r\f\v]\\{2,\\}\\)" s)
- (setq s
- (concat
- (substring s 0 (match-beginning 1))
- " "
- (substring s (match-end 1)))))
- s)
-
-
-(defun cscomp-escape-single-quotes (s)
- "Escape single-quotes in the given string S. This is for use within
-powershell.
-"
- (let ((start-pos 0))
-
- (while (string-match "\\([^']*\\)'\\(.*\\)" s start-pos)
- (setq s (concat
- (substring s 0 start-pos)
- (substring s start-pos (match-end 1))
- "''"
- (substring s (+ 1 (match-end 1))))
- start-pos (+ 2 (match-end 1)))))
- s)
-
-
-(defun cscomp--infer-type-given-decl (var-declaration
- var-index
- classname
- arglist
- instance-members)
- "Determines the type of the var declared in the given declaration.
-VAR-DECLARATION is the C# code that declares all the local vars up to
-and including the local var of interest.
-
-VAR-INDEX is the zero-based index of the local arg in that list,
-that is of interest. The initialization of that local var may
-depend on the prior local vars, which is why we need the entire
-var declaration list.
-
-CLASSNAME is the name of the class in which the local vars
-appear. This is used in the generated (synthetic) code, in case
-there is a reference to a class-static member.
-
-ARGLIST is a string with the arglist for the method that contains the
-local variable in question. This will satisfy dependencies on
-local arguments in the initializer for the var, if any.
-
-INSTANCE-MEMBERS is a C# code fragment defining instance members for the
-synthetic class. This will satisfy dependencies on instance members in
-the initializer for the var, if any.
-
-"
-
- (let ((pathlist
- (mapconcat 'identity cscomp-assembly-search-paths ",")))
- (csharp-shell-invoke-shell-fn "SetAssemblySearchPaths" pathlist))
-
-
- (let* ((massaged-decl
- (cscomp-escape-single-quotes
- (cscomp-consolidate-whitespace var-declaration)))
- (namespaces (mapconcat 'identity (cscomp-referenced-assemblies) ","))
- (command-string
- (concat "[Ionic.Cscomp.Utilities]::GetTypeGivenVarDecl('"
- massaged-decl
- "','"
- namespaces
- "','" ;; for now, no additional assembly references
- "',"
- (number-to-string var-index)
- ",'"
- classname
- "','"
- arglist
- "','"
- (cscomp-consolidate-whitespace instance-members)
- "')" )))
- (csharp-shell-do-shell-fn command-string)))
-
-
-
-
-(defun cscomp-get-completions-for-namespace (ns)
- "Gets a list of known completions (types and child namespaces)
-for the given namespace. You must have loaded an assembly containing
-types from the namespace, into the shell, for it to be known.
-See `cscomp-load-one-assembly'."
- (interactive "sNamespace: ")
- (csharp-shell-invoke-shell-fn "GetCompletionsForNamespace" ns))
-
-
-
-(defun cscomp-qualify-type-name (type-name)
- "returns fully-qualified type name for a given short TYPE-NAME.
-
-Return value is a string, or nil if the type-name is unknown.
-
-Example: (cscomp-qualify-type-name \"XmlAttribute\")
-returns \"System.Xml.XmlAttribute\"
-
-"
- (let ((result (cscomp-qualify-name type-name)))
- (cond
- ((string= (nth 0 result) "type")
- (nth 1 result))
- (t
- nil))))
-
-
-
-(defun cscomp-qualify-name (name)
- "determines if the thing is a type, namespace, or ...?
-
-Result is
-
- (list \"type\" name)
-
- or
-
- (list \"namespace\" name)
-
- or
-
- (list \"unknown\" name)
-
-"
-
- (interactive "sname to qualify: ")
- (csharp-shell-invoke-shell-fn "QualifyName" name))
-
-
-(defun cscomp-get-all-known-matches (fragment)
- "returns a list of all possible matches on a given partial name.
-The return value is like this:
-
- ((\"type\" \"fullNameOfType\")
- (\"namespace\" \"FullNameOfNamespace\")
- (\"method\" \"NameOfMethod\")
- (\"variable\" \"woof\" \"(local) System.Int32\"))
-
-"
- (interactive "sfragment to match on: ")
-
- (let* ((fixup-varlist
- (lambda (item)
- (list "variable" (car item) (cadr item))))
- (fixup-instancelist
- (lambda (item)
- (list "instance" (car item) (cadr item))))
- (instance-vars (mapcar fixup-instancelist
- (cscomp-matching-instance-vars fragment)))
- (locals (mapcar fixup-varlist
- (cscomp-matching-local-vars fragment)))
- (namespaces (mapconcat 'identity (cscomp-referenced-assemblies) ","))
- (matches (csharp-shell-do-shell-fn
- (concat "[Ionic.Cscomp.Utilities]::GetMatches('"
- fragment
- "','"
- namespaces
- "')"))))
- (append instance-vars locals matches)))
-
-
-(defun cscomp-load-one-assembly (lib)
- "Loads a assembly into the csharp-shell, which then allows
-Cscomp to do completion (etc) on the types in that library. The
-assembly should be a namespace of an assy that is in the GAC, or
-the full path of the assembly file (usually a DLL).
-"
- (interactive "sLibrary: ")
- (csharp-shell-invoke-shell-fn "LoadOneAssembly" lib))
-
-
-
-
-(defun cscomp-load-imported-namespaces ()
- "Loads assemblies for the imported namespaces into the CscompShell."
- (mapcar 'cscomp-load-one-assembly
- (cscomp-referenced-assemblies)))
-
-
-
-(defun cscomp-get-qualified-name (name)
- "Guess the fully qualified name of the class NAME, using the
-list of referenced assemblies. It returns a string if the fqn
-was found, or null otherwise."
- (interactive "sType name: ")
- (cscomp-log 2 "get-qualified-name (%s)" name)
- (let ((result (cscomp-type-exists name)))
- (if result result
- ;; else
- (let ((usinglist (cscomp-referenced-assemblies))
- fullname namespace )
-
- ;; usinglist is like this:
- ;; ("System" "System.Collections" "System.Collections.Generic" ...)
-
- (setq result nil)
- (while usinglist
- (setq namespace (car usinglist))
- (cscomp-load-one-assembly namespace)
- (setq fullname (concat namespace "." name))
- (cscomp-log 2 "checking this type: '%s'" fullname)
- (if (cscomp-type-exists fullname)
- (setq result fullname
- usinglist nil) ;; end the loop
- (setq usinglist (cdr usinglist)))))
-
- (cscomp-log 2 "get-qualified-name (%s): '%s'" name result)
-
- result)))
-
-
-(defun cscomp-reset-typeinfo-cache ()
- "Clears all entries in the type information cache."
- (interactive)
- (setq cscomp-typeinfo-cache nil))
-
-
-(defun cscomp-add-to-typeinfo-cache (name typeinfo)
- (let (new-entry new-list)
- (if (nth cscomp-typeinfo-cache-size cscomp-typeinfo-cache)
- (progn
- (setq new-entry (list name typeinfo))
- (setq new-list (list new-entry nil))
- (setcdr new-list (cdr cscomp-typeinfo-cache))
- (setq cscomp-typeinfo-cache new-list)
- (cscomp-log 1 "typeinfo cache is full"))
- ;;else
- ;; nconc?
- (setq cscomp-typeinfo-cache
- (append
- cscomp-typeinfo-cache
- (list (list name typeinfo)))))))
-
-
-(defun cscomp--get-typeinfo-from-cache (name usinglist)
- "Gets type information for the type with NAME, from the cache."
- (if (string= name "var")
- nil ;; unknown
- (let ((temp (nth 0 cscomp-typeinfo-cache))
- (index -1)
- (found nil))
- (while (and temp (not found))
- (incf index)
- (cscomp-log 4 "looking at cache item %d" index)
- (setq temp (nth index cscomp-typeinfo-cache))
- (if (string= (car temp) name)
- (setq found t)))
- (if found
- (progn
- (cscomp-log 3 "-get-typeinfo-from-cache: HIT name(%s) r(%s)"
- name (prin1-to-string (nth 1 temp)))
- (nth 1 temp))
- (cscomp-log 3 "-get-typeinfo-from-cache: MISS name(%s)" name)
- nil))))
-
-
-
-(defun cscomp-get-typeinfo (name)
- "Return the class info list for the class NAME. This function first
-checks to see if the class info is cached. If so, it returns the
-cached class info. Otherwise, it creates the type info list. Each
-element of the list returned by this function is itself a list whose
-car is a possible completion and whose cdr gives additional
-informations on the completion - the property type, or the param
-list and return type for a method, etc."
- (interactive "sTypename: ")
-
- (if (string= name "var")
- (progn
- (cscomp-log 2 "ENTER get-typeinfo name(%s)...result:nil" name)
- nil) ;; unknown
-
- (cscomp-log 2 "ENTER get-typeinfo name(%s)...trying cache..." name)
-
- (let* ((usinglist (cscomp-referenced-assemblies))
- (type-info (cscomp--get-typeinfo-from-cache name usinglist))
- (ulist (mapconcat 'identity usinglist ", "))
- namespace
- qualified-type )
-
- ;; load all the assemblies mentioned in the using clauses
- (while usinglist
- (setq namespace (car usinglist))
- (cscomp-load-one-assembly namespace)
- (setq usinglist (cdr usinglist)))
-
- (if (null type-info)
- (progn
- (setq qualified-type
- (csharp-shell-exec-and-eval-result
- (concat
- "[Ionic.Cscomp.Utilities]::QualifyType('"
- ;;(cscomp-escape-string-for-powershell name)
- ;; dont need to escape if using single quotes
- name
- "','"
- ulist
- "')")))
-
- (cscomp-log 2 "get-typeinfo...(%s)..." (prin1-to-string
qualified-type))
-
- (if qualified-type
- (setq type-info
- (csharp-shell-exec-and-eval-result
- (concat "[Ionic.Cscomp.Utilities]::GetTypeInfo('"
- (car qualified-type) ; type name
- "', '"
- (cadr qualified-type) ; assembly name
- "')" ))))
- (if type-info
- (cscomp-add-to-typeinfo-cache name type-info))))
-
- type-info)))
-
-
-(defun cscomp-get-type-ctors (type-name)
- "Retrieve constructors from CscompShell for the type named by TYPE-NAME.
-"
- (interactive "sType name: ")
- (csharp-shell-invoke-shell-fn "GetConstructors" type-name))
-
-
-
-
-(defun cscomp-split-by-dots (s)
- "When the string contains a dot, this fn returns a 2-element
-list (TOKEN1 TOKEN2). TOKEN1 is the substring of s that precedes
-the last dot. TOKEN2 is the substring that follows the last dot.
-
-When the string does not contain a dot, this fn returns a
-2-element list in which the first element is nil and the 2nd
-element is the entire string.
-
-"
- (cscomp-log 2 "split-by-dots: s[%s]" s)
- (if (string-match "\\(.*\\)\\.\\(.*\\)" s)
- (let ((result (list (match-string 1 s) (match-string 2 s))))
- (cscomp-log 2 "split-by-dots: %s" (prin1-to-string result))
- result)
- (list nil s))) ;; it's a single atom
-
-
-
-
-(defun cscomp-parse-csharp-expression-before-point ()
- "Parses the text at point, and returns the results.
- Side effect: sets markers to the beginning
- (cscomp-current-beginning) and end (cscomp-current-end)
- of the parsed expression.
-
-The return value is a list (POSN (TOKEN1 TOKEN2)) , where POSN is
-the position in the buffer of the beginning of TOKEN1 and TOKEN1
-and TOKEN2 are the two tokens surrounding the prior dot.
-
-Some examples.
-
-#1
-Suppose System.Diagnostics.D is the text that appears prior to
-point. This function would return the list
-
- (888 (\"System.Diagnostics\" \"D\"))
-
-...if 888 was the position of the beginning of the word System.
-
-
-#2
-Suppose new System.DateTime the text that appears prior to
-point. This function would return the list
-
- (721 (nil \"new System.DateTime\"))
-
-...if 721 is the position of the beginning of the word \"new\".
-
----
-
-It's just an exercise in syntactically-aware string parsing. It
-uses some cc-mode magic to do some of that.
-
-If the text preceding point doesn't look like two tokens, this fn
-returns nil, and does not set the markers.
-
-"
- (interactive)
-
- (cscomp-log 2 "parse-csharp-expression-before-point: point(%d)" (point))
-
- (save-excursion
- (let ((opoint (point))
- (cycle-count 0)
- (dot-count 0)
- (regex "[-\\+\\*\\/%,;|( {})=\\.]")
- snip done m1
- (paren-depth 0)
- result)
-
- ;; Repeatedly step backward, over whitespace and c# source tokens.
- ;; The regex above defines what we skip back TO. The first cycle
- ;; through, we skip back to any of the set of
- ;; syntactically-relevant symbols including + - * / % , ; | ( ) {
- ;; } = or dot (.). If the first step backwards finds a dot, we change
the
- ;; regex to find anything in that list EXCEPT the dot.
- ;; Stepping backwards twice gives us a pair of tokens, which we can then
- ;; use to perform completion on .
-
- (while (not done)
-
- (skip-chars-backward "\t ")
-
- (cond
-
- ((and (eq cycle-count 0) ;; first time through
- (eq (char-before) 40)) ;; 40 = open paren - means we want fn
completion
- (backward-char)) ;; backup
-
- ((eq (char-before) 34) ;; 34 = doublequote
- (backward-char 1) ;; move back into the quoted string
- (let ((limits (c-literal-limits)))
- (if (consp limits)
- (c-safe (goto-char (car limits)))))) ;; goto beginning of
literal string
-
- ;; ((eq (char-before) 41) ;; 41 = close paren - means
we want fn completion
- ;; (incf paren-depth)
- ;; (backward-char))
- ;;
- ;; ((and
- ;; (eq (char-before) 40) ;; 40 = open paren
- ;; (> paren-depth 0)) ;; we have a pending close
paren (moving backwards)
- ;; (decf paren-depth)
- ;; ;;(funcall skip-back))
- ;; (backward-char))
-
- ;; ((or
- ;; (eq (char-before) 32) ;; space
- ;; (eq (char-before) ?\t)) ;; tab
- ;; (funcall skip-back))
-
- ((re-search-backward regex nil t)
- (cond
-
- ((eq (char-after) 41) ;; 41 = close paren - means we want fn
completion
- (incf paren-depth)
- t)
-
- ((and
- (eq (char-after) 40) ;; 40 = open paren
- (> paren-depth 0)) ;; we have a pending close paren (moving
backwards)
- (decf paren-depth)
- ;;(funcall skip-back))
- t)
-
- ((or
- (eq (char-after) 32) ;; space
- (eq (char-after) ?\t)) ;; tab
- (if (not m1) (setq m1 (point)))
- t) ;; do nothing else
-
- ;; The char after is a dot. Ergo, change the regex.
- ;; The next step back will not stop on dot.
- ((eq (char-after) ?.)
- (setq m1 (point))
- (setq regex "[-\\+\\*\\/%,;|( {})=]"))
-
- (t
- (setq done t))))
-
- (t
- (backward-char)))
-
- (incf cycle-count)) ;; count of steps backward
-
- ;; set markers, before consolidating whitespace
- (let ((beg (1+ (or m1 (point)))))
-
- (cscomp-log 2 "parse-csharp-expression-before-point: reset begin,end
to (%d,%d)"
- beg opoint)
-
- ;; beginning: right after the dot (if there is one)
- (set-marker cscomp-current-beginning beg)
- (set-marker cscomp-current-end opoint ))
-
- (setq snip
- (cscomp-consolidate-whitespace
- (buffer-substring-no-properties (1+ (point)) opoint)))
-
- (cscomp-log 2 "parse-csharp-expression-before-point: B snip(%s)" snip)
- (setq result (list (1+ (point))
- (if (eq 0 (string-match "new " snip))
- (list nil snip)
- (cscomp-split-by-dots snip))))
-
- (if (called-interactively-p 'any)
- ;; If called interactively, show the result at
- ;; the bottom of the screen.
- (message "result: %s" (prin1-to-string result)))
-
- result)))
-
-
-
-
-(defun cscomp--random-symbol-name ()
- (random t)
- (loop
- for i below 10
- collect (+ (if (= (random 2) 0) 65 97) (random 26)) into auth
- finally return (concat auth)))
-
-(defun cscomp-last-char-in-string (s)
- (let ((ix (length s)))
- (elt s (- ix 1))))
-
-
-
-(defun cscomp--infer-type-of-symbol (symbol initializers args)
- "A helper fn. This infers the type of a given SYMBOL, assuming
-the provided variable initializers (INITIALIZERS) and method
-arguments (ARGS) that may be used to initialize the named symbol.
-
-The return value is a list (VAR-TYPE VAR-POSN) , where VAR-TYPE
-is a string, a typename, and VAR-POSN is a list of (START FINISH)
-that describes where in the buffer the variable was declared. In
-the case of contrived variables, which are used to infer the type
-of arbitrary expressions, the VAR-POSN is not valid.
-
-"
- (let* ((result nil)
- (decl-count 0)
- (brace-count 0)
- (prior-var-decls "")
- (containing-type (csharp-analysis-current-class)))
-
- ;; look at local args first
- (loop
- for x in args do
- (if (not result)
- (progn
- (cscomp-log 3 "infer-type-of-symbol: looking at arg (%s)"
- (prin1-to-string x))
- (let ((var-name (cadr x)))
- ;; If this arg decl is the same name as the one
- ;; we want, things are simple. We know the type.
- (if (string= var-name symbol)
- (let
- ((var-type (caddr x))
- (var-posn ;; pair: start and end of var decl
- (mapcar 'cscomp-pos-at-line-col
- (cdr (csharp-analysis-tag-location x)))))
- (cscomp-log 3 "infer-type-of-symbol: found arg %s (%s)"
- symbol var-type)
- (setq result (list var-type var-posn))))))))
-
-
- ;; now look at local variables
- (while (and initializers (not result))
- (let* ((x (car initializers))
- (var-name (cadr x))
- (var-id (csharp-analysis-tag-id x))
- (var-type (caddr x))
- (var-posn ;; pair: start and end of var decl
- (mapcar 'cscomp-pos-at-line-col
- (cdr (csharp-analysis-tag-location x)))))
-
- (cscomp-log 3 "infer-type-of-symbol: looking at var (%s)"
- (prin1-to-string x))
-
- ;; If this var decl is the same name as the one
- ;; we want.
- (if (string= var-name symbol)
- (progn
- ;; Handle var types - need to determine the actual type.
- ;;
- ;; To do that, compile the var declaration, then inspect the IL
- ;; to determine the var types.
- ;;
- ;; This engine will determine the var type, in some portion of
- ;; the cases.
- ;;
- ;; It will handle:
- ;;
- ;; - simple var declarations that have no dependencies on other
vars
- ;; - cascaded var decls that depend on other local vars.
- ;; - var whose initializaiton depends on a method argument
- ;; - var whose initialization depends on an instance var
- ;; - var decls in foreach loops
- ;; - var decls in using blocks
- ;;
-
- ;; if the type of the variable is "var"
- (if (string= var-type "var")
- (progn
- (let* ((member-list (csharp-analysis-class-members
containing-type))
- (name-of-containing-type (cadr containing-type))
- (parent-tag
- (csharp-analysis-find-parent-tag-by-id-from-ast
(list containing-type) var-id))
- (parent-flavor (and parent-tag
(csharp-analysis-tag-flavor parent-tag)))
- (var-init (assoc 'initialvalue x))
- (this-decl
- (cond
- ((string= parent-flavor "foreach")
- (concat
- "foreach (var "
- var-name
- " in "
- (buffer-substring-no-properties (elt var-posn
0) (elt var-posn 1))
- ") {}")) ;; handle foreach
-
- (var-init ;; for contrived variables
- (concat
- "var " var-name " = " (cadr var-init) ";"))
-
- (t
- (cscomp-log 3 "not a foreach loop.")
- (let ((frag
- (buffer-substring-no-properties
- (elt var-posn 0) (elt var-posn 1))))
- (if (not (string-match ";[ \t]*$" frag))
- (progn
- (message "appending semi to frag: %s"
frag)
- (concat frag ";"))
- (progn
- (message "var decl (no semi needed):
%s" frag)
- frag))))))
- inferred-type)
-
- ;; append close-braces for any open for or foreach loops
- (while (> brace-count 0)
- (setq brace-count (- brace-count 1)
- this-decl (concat this-decl "}")))
-
- ;; Infer the type. This generates C# code, compiles it,
- ;; and then inspects the IL to determine the type.
- (setq inferred-type
- (cscomp--infer-type-given-decl
- (concat prior-var-decls " " this-decl)
- decl-count
- name-of-containing-type
- (cscomp-produce-csharp-arglist-block-from-tag
args)
- (cscomp-produce-instance-member-code-fragment
member-list)))
-
- (if (and inferred-type (string= (car inferred-type)
"type"))
- (setq var-type (cadr inferred-type))
- (message "%s" (prin1-to-string inferred-type))
- ))))
-
- (cscomp-log 2 "infer-type-of-symbol: result %s.GetType() = (%s)"
- symbol var-type)
- (setq result (list var-type var-posn)))
-
- ;; else (it's not the variable we want)
- ;; Remember it. It may be necessary to initialize our var of
interest.
- (let ((this-var-decl
- (buffer-substring-no-properties (elt var-posn 0) (elt
var-posn 1)))
- emitted)
-
- (if (string= var-type "var")
- (let* ((containing-type (csharp-analysis-current-class))
- (parent-tag
- (csharp-analysis-find-parent-tag-by-id-from-ast
- (list containing-type)
- var-id))
- (parent-flavor (and parent-tag
(csharp-analysis-tag-flavor parent-tag))))
-
- (if (string= parent-flavor "foreach")
- ;; its a var in a foreach
- (setq brace-count (1+ brace-count)
- emitted t
- prior-var-decls (concat prior-var-decls
- " foreach (var "
- var-name
- " in "
- this-var-decl
- ") {\n")))))
- (if (not emitted)
- ;; include this decl in the set of prior decls
- (progn
- (setq prior-var-decls (concat prior-var-decls " "
this-var-decl)
- decl-count (1+ decl-count))
- ;; add a semicolon if necessary. This happens in
- ;; case of a using clause, for example.
- (if (/= (cscomp-last-char-in-string this-var-decl) 59)
- (setq prior-var-decls (concat prior-var-decls ";")))
- )))))
-
- (setq initializers (cdr initializers)))
-
- result))
-
-
-
-
-(defun cscomp-infer-type-of-expression (expr)
- "Use the sourcecode analysis results to infer the type of the
-given expression, EXPR, which must be a string. Returns a
-typename, or nil if unknown.
-
-To infer the type, this fn generates C# source code that includes
-the expression in question, compiles that code, and inspects the
-IL to determine the type of the expression.
-
-The return value is the ???
-
-See also `cscomp-qualify-local-var'.
-"
-
- ;; To generate compilable code, we need to include all relevant
- ;; variables and arguments, that the expression in question may depend
- ;; upon. So, iterate through arguments and local variables, inject all
- ;; of them into a compilable source fragment, then pass that fragment
- ;; off to the CscompUtilities assembly to compile it and inspect the
- ;; result.
- ;;
-
- (cscomp-log 3 "ENTER infer-type-of-expr: (%s)" (or expr "--"))
-
- (let* ((contrived-name (cscomp--random-symbol-name))
- (contrived-var
- (list 'var contrived-name "var"
- (list 'initialvalue expr) ;; the infererence logic will use
this
- '(location (1 1) (1 2)) ;; dummy
- '(id 0)))
- (initializers
- (append (csharp-analysis-local-variables) (list contrived-var)))
- (args (csharp-analysis-local-arguments)))
- (cscomp--infer-type-of-symbol contrived-name initializers args)))
-
-
-
-
-(defun cscomp-qualify-local-var (symbol)
- "Use the sourcecode analysis results to classify the
-SYMBOL as a local variable.
-
-If the symbol is a local variable, this fn returns a list, 1st
-elt is the variable type, and the second elt is a vector,
-containing the position of its definition.
-
-If the symbol is not recognized as a local variable, this fn
-returns nil.
-
-See also `cscomp-qualify-instance-var'.
-"
- (cscomp-log 3 "ENTER qualify-local-var: (%s)" (or symbol "--"))
- (if (or
- (null symbol)
- (eq 0 (string-match cscomp--new-regexp symbol)))
- (progn
- (cscomp-log 3 "EXIT qualify-local-var: (%s)" (or symbol "--"))
- nil)
- (let ((locals (csharp-analysis-local-variables))
- (args (csharp-analysis-local-arguments)))
- (cscomp--infer-type-of-symbol symbol locals args))))
-
-
-
-
-(defun cscomp-pos-at-line-col (position)
- "Return the char position at the given line/column POSITION,
-which is of the form (LINE . COLUMN).
-
-"
- (let ((line (nth 0 position))
- (column (nth 1 position)))
- (save-excursion
- (goto-char (point-min))
- (forward-line (- line 1))
- (+ (point) (- column 1)))))
-
-
-
-
-(defun cscomp-qualify-instance-var (symbol)
- "Use the csharp source analysis results to classify the
-name as an instance variable. Returns a list, 1st elt is the
-variable type, and the second elt is a vector, containing
-the position of its definition.
-
-See also `cscomp-qualify-local-var'.
-
-"
- (if (or
- (null symbol)
- (eq 0 (string-match cscomp--new-regexp symbol)))
- nil
- (let ((ivars (csharp-analysis-instance-variables))
- (result nil))
- (while (and ivars (not result))
- (let* ((x (car ivars))
- (var-name (cadr x))
- (var-type (caddr x))
- (var-posn ;; pair: start and end of var decl
- (mapcar 'cscomp-pos-at-line-col
- (cdr (csharp-analysis-tag-location x)))))
-
- (if (string= var-name symbol)
- (progn
- (cscomp-log 2 "qualify-instance-var: found %s (%s)"
- symbol var-type)
- (setq result (list var-type var-posn))))
- (setq ivars (cdr ivars))))
- result)))
-
-
-
-
-(defun cscomp-completion-list-for-ns (nsinfo)
- "Build a completion list from the NSINFO list, as returned by the
-Ionic.Cscomp.Utilities.GetCompletionsForNamespace function.
-
-If the incoming NSINFO list looks like this:
-
- (\"System.Collections.Generic\"
- (types (\"ArraySortHelper`1\"
- \"ArraySortHelper`2\"
- \"ByteEqualityComparer\"
- \"Comparer`1\"
- \"Dictionary`2\"
- \"EqualityComparer`1\"))
- (namespaces (\"Something1\"
- \"Something2`2\")))
-
-Then the return value is like this:
-
- (\"ArraySortHelper<T1,T2> | (type)\"
- \"ArraySortHelper<T1> | (type)\"
- \"ByteEqualityComparer | (type)\"
- \"Comparer<T1> | (type)\"
- \"Dictionary<T1,T2> | (type)\"
- \"EqualityComparer<T1> | (type)\"
- \"Something1 | (namespace)\"
- \"Something2`2 | (namespace)\")
-
-It's just a transformation from one data format to another.
-
-"
- (let* ((typelist (cadr (cadr nsinfo)))
- (nslist
- (mapcar '(lambda (item) (concat item " | (namespace)") )
- (cadr (caddr nsinfo)))))
- (cscomp-fix-generic-method-strings typelist)
- (setq typelist (mapcar '(lambda (item) (concat item " | (type)") )
- typelist))
- ;;(reverse (sort (append typelist nslist) 'string-lessp))
- (sort (append typelist nslist) 'string-lessp)
- ))
-
-
-
-(defun string-replace-char (s c1 c2)
- "Replace all occurrences of char C1 in string with char C2.
-Return the modified string."
- (let ((string-len (length s))
- (ix 0))
- (while (< ix string-len)
- (if (eq (aref s ix) c1)
- (aset s ix c2))
- (incf ix)))
- s)
-
-
-
-(defun cscomp-fix-one-generic-method-string (descrip)
- "Reformat the generic type string like System.Action`1
-into a C#-friendly System.Action<T1> . Returns the reformatted
-string. Returns nil if reformat was unnecessary.
-"
- (cond
-
- ;; input: System.Converter`2[T,TOutput]
- ;; output: System.Converter<T,TOutput>
- ((string-match "^\\(.+\\)`[1-9]\\[\\([^]]+\\)\\]$" descrip)
- (concat
- (match-string 1 descrip)
- "<"
- (match-string 2 descrip)
- ">"))
-
- ;; input: System.Collections.Generic.Dictionary`2
- ;; output: System.Collections.Generic.Dictionary<T1,T2>
- ((string-match "^\\(.+\\)`\\([1-9]\\)\\(.*\\)$" descrip)
- (let ((z (string-to-number (match-string 2 descrip)))
- (new-name (concat (match-string 1 descrip) "<"))
- (i 0))
- (while (< i z)
- (setq i (1+ i)
- new-name (concat new-name (format "T%d" i)))
- (if (< i z)
- (setq new-name (concat new-name ","))))
- (setq new-name (concat new-name ">" (match-string 3 descrip)))))
-
- ;; anything else
- (t nil)))
-
-
-
-(defun cscomp-fix-generic-method-strings (clist)
- "Fixup a list of strings, that may have generic method types
-in them, to have C#-friendly formats. This fn does the modifications
-in place. The return value is the original list, with the internal values
-modified.
-
-"
- (let ((count (list-length clist))
- (n 0)
- new-name
- cur-elt)
- (while (< n count)
- (setq cur-elt (nth n clist))
- (if (setq new-name (cscomp-fix-one-generic-method-string cur-elt))
- (setf (nth n clist) new-name))
- ;; the following will affect the string in the list
- (string-replace-char cur-elt ?+ ?.)
- (incf n)))
- clist)
-
-
-
-(defun cscomp-fix-generics-in-descrip-line (descrip-line)
- "Fixup a string, a description of a method or property, to
-have C#-friendly generic types.
-
-Eg, convert (Method) public (System.Converter`2[T,TOutput] converter) returns
List`1[TOutput]
-
-to (Method) public (System.Converter<T,TOutput> converter) returns
List<TOutput>
-
-"
- (let ((tokens (split-string descrip-line "[ \t]" t)))
- (cscomp-fix-generic-method-strings tokens)
- (mapconcat 'identity tokens " ")))
-
-
-
-
-
-(defun cscomp-completion-list-for-type (typeinfo)
- "Build a completion list from the TYPEINFO list, as returned by the
-Ionic.Cscomp.Utilities.GetTypeinfo function in the CscompShell. The list
-is used when performing completions on an instance of a given type.
-
-For input that looks like this:
-
- (\"System.IO.DriveInfo\" 'type
- ((\"Name\" 'property \"System.String\" (typemodifiers
\"readonly\" \"public\"))
- (\"AvailableFreeSpace\" 'property \"System.Int64\" (typemodifiers
\"readonly\" \"public\"))
- (\"TotalFreeSpace\" 'property \"System.Int64\" (typemodifiers
\"readonly\" \"public\"))
- (\"VolumeLabel\" 'property \"System.String\" (typemodifiers
\"public\")))
-
- ((\"Equals\" method \"System.Boolean\" (\"System.Object obj\")
(typemodifiers \"public\"))
- (\"GetDrives\" method \"System.IO.DriveInfo[]\" nil (typemodifiers
\"public\" \"static\"))
- (\"ToString\" method \"System.String\" nil (typemodifiers \"public\"))))
-
-
-The output looks like this:
-
- ((\"ToString\" \"(Method) public () returns System.String\")
- (\"GetDrives\" \"(Method) public static () returns
System.IO.DriveInfo[]\")
- (\"Equals\" \"(Method) public (System.Object obj) returns
System.Boolean\")
- (\"VolumeLabel\" \"(Property) public System.String\")
- (\"TotalFreeSpace\" \"(Property) readonly public System.Int64\")
- (\"AvailableFreeSpace\" \"(Property) readonly public System.Int64\")
- (\"Name\" \"(Property) readonly public System.String\"))
-
-"
-
- (let (result
- (tname (car typeinfo))
- (props (caddr typeinfo))
- (methods (cadddr typeinfo))
- (fields (caddr (cddr typeinfo)))
- modifiers)
-
- (cscomp-log 3 "completion-list-for-type: typename(%s)" tname)
-
- (while props
- (let ((one-prop (car props) ) )
- (setq modifiers
- (mapconcat 'identity (cdr (nth 3 one-prop)) " "))
- (setq result
- (append (list
- (list
- (car one-prop) ;; the name of the property
-
- ;; additional information about the property
- (concat "(Property) "
- modifiers ;; modifiers on this prop
- " "
- (nth 2 one-prop) ;; type of the prop
- )))
- result)))
- (setq props (cdr props)))
-
- (while methods
- (let ((one-method (car methods)) params)
- (setq modifiers
- (mapconcat 'identity (cdr (nth 4 one-method)) " "))
- (setq params
- (if (nth 3 one-method)
- (concat "("
- (mapconcat 'identity (nth 3 one-method) ", ")
- ")")
- ;; else
- "()" ))
-
- (setq result
- (append (list
- (list
- (car one-method) ;; the name of the method
-
- ;; additional information about the method (in a
string)
- (concat "(Method) "
- modifiers ;; modifiers on this prop
- " "
- params
- " returns "
- (nth 2 one-method) ;; return type of the
method
- )
- ))
- result)))
-
- (setq methods (cdr methods)))
-
-
- (while fields
- (let ((one-field (car fields)))
- (setq modifiers
- (mapconcat 'identity (cdr (nth 3 one-field)) " "))
- (setq result
- (append (list
- (list
- (car one-field) ;; the name of the field
-
- ;; additional information about the field (in a string)
- (concat "(Field) "
- modifiers ;; modifiers on this prop
- " "
- (nth 2 one-field) ;; type of the field
- )
- ))
- result)))
-
- (setq fields (cdr fields)))
-
-
- (cscomp-log 2 "completion-list-for-type: result: "
- (prin1-to-string result))
- ;;(print result (get-buffer "*Messages*"))
- result))
-
-
-
-(defun cscomp-completion-list-for-ctors (ctor-info)
- "Build a completion list from the CTOR-INFO list, as returned by the
-Ionic.Cscomp.Utilities.GetConstructors function in the CscompShell. The list
-is used when performing completions on a constructor for a given type.
-
-The input looks like:
- (\"System.String\" 'type
- (:constructors
-
- ((:typemodifiers (\"public\")
- :arguments ((\"value\" 'variable
- (:type \"System.Char*\"))))
-
- (:typemodifiers (\"public\")
- :arguments ((\"value\" 'variable
- (:type \"System.Char*\"))
- (\"startIndex\" 'variable
- (:type \"System.Int32\"))
- (\"length\" 'variable
- (:type \"System.Int32\"))))
-
-The output is a completion list, which is a list of (NAME DESCRIP) pairs.
-The DESCRIP of each pair should have the arguments for each constructor.
-
-That list is later transformed into a structure that is suitable
-for use in a popup menu.
-
-"
- (let (result
- (tname (car ctor-info))
- (ctors (cadr (caddr ctor-info))))
-
- (cscomp-log 2 "completion-list-for-ctors: typename(%s)" tname)
-
- (while ctors
- (let* ((one-ctor (car ctors))
- (modifiers (mapconcat 'identity (nth 1 one-ctor) " "))
- (params
- (if (nth 3 one-ctor)
- (concat "("
- (mapconcat
- '(lambda (x)
- (concat
- (cadr (caddr x))
- " "
- (car x)))
- (nth 3 one-ctor) ", ")
- ")")
- ;; else
- "()" )))
- (setq result
- (append (list
- (list tname ;; name of the ctor
- ;; description for this ctor
- (concat "(Constructor) "
- modifiers ;; modifiers on this prop
- " "
- params
- )))
- result)))
- (setq ctors (cdr ctors)))
-
- (cscomp-log 3 "completion-list-for-ctors: result: "
- (prin1-to-string result))
- result))
-
-
-
-;; (defun cscomp-popup-xemacs-completion-menu (completion-list)
-;; (let* ((items
-;; (sort
-;; ;; Change each item in the completion list from the form
-;; ;; return-value method-name(args)
-;; ;; to the form
-;; ;; method-name(args) : return-value
-;; (mapcar
-;; (lambda (completion)
-;; (let ((completion-short (nth 0 completion))
-;; (completion-long (nth 1 completion)))
-;; (if completion-long
-;; (let ((chop-pos (string-match " " completion-long)))
-;; (concat
-;; (substring completion-long (1+ chop-pos)
-;; (length completion-long))
-;; " : "
-;; (substring completion-long 0 chop-pos)))
-;; completion-short)))
-;; completion-list)
-;; 'string<))
-;; (menu
-;; (cons
-;; "Completions"
-;; (mapcar
-;; (lambda (item)
-;; (vector item (list 'cscomp-insert-completion item)))
-;; items))))
-;; (popup-menu-and-execute-in-window menu (selected-window))))
-
-
-
-
-(defun cscomp-sort-completion-list (lst)
- (if (consp (car lst))
- (sort lst
- '(lambda (e1 e2)
- (string< (car e1) (car e2))))
- (sort lst
- '(lambda (e1 e2)
- (string< e1 e2)))))
-
-
-
-(defun cscomp-find-all-ns-completions (fragment lst &optional exact-match )
- "Find all completions for FRAGMENT in LST. If EXACT-MATCH is true,
-then...? LST is a simple list of strings, as obtained from
-`cscomp-completion-list-for-ns'.
-"
- (let ((result nil))
- (while lst
- (let ((candidate (car lst)))
- (if (or (and exact-match (string= fragment candidate))
- (and (not exact-match) (equal 0 (string-match (concat "^"
fragment) candidate))))
- (progn
- (message " HIT")
- (setq result (append (list candidate) result)))))
- (setq lst (cdr lst)))
-
- (setq cscomp-current-fragment fragment)
-
- ;; sort, and then transform into a list of (NAME DESCRIP) pairs:
- (mapcar
- '(lambda (item)
- (if (string-match "^\\([^|]+\\) +| +\\(.+\\)$" item)
- (list (match-string 1 item)
- (match-string 2 item))
- item))
- (cscomp-sort-completion-list result))))
-
-
-
-
-(defun cscomp-find-all-type-completions (fragment lst static &optional
exact-match)
- "Find all completions in LST for FRAGMENT. In practice,
-FRAGMENT is a string containing the characters following the last
-dot. Eg, if the user typed System.IO.Dir, then FRAGMENT would be
-\"Dir\".
-
-LST is a list obtained from `cscomp-completion-list-for-type'.
-
-If STATIC is non-nil, then match only non-static props/fields/methods.
-Otherwise, match only static fields/props/methods.
-
-If EXACT-MATCH is true, then only the completions that match the
-FRAGMENT exactly are returned. Normally, EXACT-MATCH is not
-true, and in thi case, the completions that start with the
-FRAGMENT are returned.
-
-The result is...a simple list of strings.
-
-"
-
-;; For illustration, the LST for DriveInfo looks like this:
-;; (
-;; ("Name" "(Property) readonly public System.String")
-;; ("DriveType" "(Property) readonly public System.IO.DriveType")
-;; ("DriveFormat" "(Property) readonly public System.String")
-;; ("IsReady" "(Property) readonly public System.Boolean")
-;; ("AvailableFreeSpace" "(Property) readonly public System.Int64")
-;; ("TotalFreeSpace" "(Property) readonly public System.Int64")
-;; ("TotalSize" "(Property) readonly public System.Int64")
-;; ("RootDirectory" "(Property) readonly public System.IO.DirectoryInfo")
-;; ("VolumeLabel" "(Property) public System.String")
-;; ("Equals" "(Method) public (System.Object) returns System.Boolean")
-;; ("GetDrives" "(Method) public static () returns System.IO.DriveInfo[]")
-;; ("GetHashCode" "(Method) public () returns System.Int32")
-;; ("GetType" "(Method) public () returns System.Type")
-;; ("ToString" "(Method) public () returns System.String")
-;; )
-
-
- (let ((result nil))
- (while lst
- (let* ((candidate (car lst))
- (member-name (car candidate))
- (descrip (cadr candidate))
- (is-static (string-match " static " descrip))
- (is-match (and
- (if static is-static (not is-static))
- (if exact-match
- (string= fragment member-name)
- (equal 0 (string-match fragment member-name))))))
-
- (cscomp-log 4 "find-all-type-completions, looking at %s %s"
- (prin1-to-string candidate)
- (if is-match "MATCH" ""))
-
- (if is-match
- (setq result (append (list candidate) result))))
-
- (setq lst (cdr lst)))
-
- (cscomp-log 3 "find-all-type-completions, result: %s"
- (prin1-to-string result))
- ;;(print result (get-buffer "*Messages*"))
-
- (setq cscomp-current-fragment fragment)
- (cscomp-sort-completion-list result)))
-
-
-
-
-(defvar cscomp-primitive-types
- (list
- '("string" "System.String")
- '("byte" "System.Byte")
- '("sbyte" "System.SByte")
- '("char" "System.Char")
- '("double" "System.Double")
- '("float" "System.Float")
- '("bool" "System.Boolean")
- '("int" "System.Int32")
- '("long" "System.Int64")
- '("short" "System.Int16")
- '("uint" "System.UInt32")
- '("ulong" "System.UInt64")
- '("ushort" "System.UInt16")
- )
-
- "a list that maps primitive C# types to their unboxed types.")
-
-
-
-(defun cscomp-map-primitive-type (type)
- "Maps the primitive type \"short name\" to the expanded name of
-the type, and returns that expanded name. For example, \"bool\"
-maps to \"System.Boolean\" .
-
-If type is not a primitive type, the result is nil.
-"
-
- (if (member type (mapcar 'car cscomp-primitive-types))
- (let ((result nil)
- (lst cscomp-primitive-types)
- item )
- (while lst
- (setq item (car lst))
- (if (string= type (car item))
- (and
- (setq result (cadr item))
- (setq lst nil))
- ;;else
- (setq lst (cdr lst))))
- result )
- ;;else
- nil ))
-
-(defun cscomp-find-completion-for-split (split beginning-of-token1 &optional
reuse-results)
-"Find the possible completions for a given string, which has
-been previously parsed. This is where the main work of the module
-is performed.
-
-SPLIT is a list of (TOKEN1 TOKEN2), as returned from
-`cscomp-split-by-dots'.
-
-If the user has typed something followed by a dot, optionally
-followed by an fragment after the dot, and then asked for
-completions via `cscomp-complete-at-point-menu' or
-`cscomp-complete-at-point', then this function gets invoked, with
-TOKEN1 containing what precedes the dot, and TOKEN2 containing
-what follows the dot. For example, TOKEN1 may be a C# namespace,
-a class name, a variable name (local variable or a method or
-property or field name on the current class), or explicitly,
-\"this\" . TOKEN2 may be the empty string, or a fragment of a
-name, corresponding to a method property or field belonging to
-the thing represented by the first token. The goal is to find a
-completion for the second token, given the context of the first
-token.
-
-The return value is a list. For example, if the user types the
-name of an int variable, then a dot, then asks for completions,
-the return value is:
-
- ((\"CompareTo\" \"(Method) sealed public (System.Int32 value) returns
System.Int32\")
- (\"CompareTo\" \"(Method) sealed public (System.Object value) returns
System.Int32\")
- (\"Equals\" \"(Method) sealed public (System.Int32 obj) returns
System.Boolean\")
- (\"Equals\" \"(Method) public (System.Object obj) returns
System.Boolean\")
- (\"GetHashCode\" \"(Method) public () returns System.Int32\")
- (\"GetType\" \"(Method) public () returns System.Type\")
- (\"GetTypeCode\" \"(Method) sealed public () returns System.TypeCode\")
- (\"ToString\" \"(Method) sealed public (System.String format,
System.IFormatProvider provider) returns System.String\")
- (\"ToString\" \"(Method) sealed public (System.IFormatProvider provider)
returns System.String\")
- (\"ToString\" \"(Method) public () returns System.String\")
- (\"ToString\" \"(Method) public (System.String format) returns
System.String\"))
-
-
-Another Example: if the user types System.Diag and asks for completions,
-then SPLIT will be (\"System\" \"Diag\") and the returned completion
-list will contain \"Diagnostics\".
-
-If the user has simply typed a string, and asked for completions,
-then TOKEN1 will be nil and TOKEN2 will contain the string.
-This fn then finds possible completions for that single string.
-
-"
- (cscomp-log 2 "find-completion-for-split: A: '%s' '%s'"
- (car split) (cadr split))
-
-
- ;; In most cases, p1 is what precedes the final dot, p2 is what
- ;; follows. When there is no dot, p1 is nil. when this is an
- ;; invocation of a constructor, even if the typename contains a dot,
- ;; then p1 is nil and p2 contains "new ZZZ" where ZZZ is the typename,
- ;; with any qualifying namespace.
- ;;
- ;;
- ;; Possibilities:
- ;;
- ;; 1. p1 is a namespace like System.Xml p2 is empty, or a fragment, like
XPa.
- ;; In this case we need to find types or child namespaces in the given
- ;; namespace that match the given fragment.
- ;;
- ;; 2. p1 is "this" and p2 is a fragment of a name of a class
field/prop/method.
- ;; In this case, complete on the members of the enclosing class.
- ;;
- ;; 3. p1 is the name of a local variable, and p2 is empty or a fragment.
- ;; In this case, complete with a field, prop, or method on that variable.
- ;; Must know or learn the type of the variable in that case.
- ;;
- ;; 4. p1 is nil, and p2 is the partial name of a local variable.
- ;; In this case, complete with the name of a local field, prop, or method
- ;; that matches.
- ;;
- ;; 5. p1 is nil, and p2 is "new ZZZ", where ZZZ is the partial name of a
type.
- ;; In this case, complete with the name of a type or namespace
- ;; that matches the ZZZ portion of p2.
- ;;
- ;; 6. p1 is the name of a type, like System.Console, and p2 is something.
- ;; In this case, complete with static field, prop, and methods on
- ;; that type.
- ;;
- ;; 7. p1 is the name of a primitive type, like byte or int.
- ;; In this case, replace it with the expanded type, and complete as
- ;; in case 5.
- ;;
- ;; 8. others?
- ;;
- ;; =============================================
- ;;
- ;; There are two sources for completion possibilities. For known types,
- ;; the possibilities come from introspection, done through the CscompShell.
- ;; So, for System.Xml.XmlDocument, we send a message to the shell and get
back
- ;; all the known fields/props/methods of that .NET type. For System.Xml.X, we
- ;; send a message to the CscompShell and get back a list of types and
namespaces
- ;; that match.
- ;;
- ;; For unknown types - currently the only "unknown" qualifier is "this." -
- ;; use the source code analysis results to find fields/props/methods.
- ;;
-
- (let* ((p1 (car split)) ;; part 1 - usually what precedes the dot
- (p2 (cadr split)) ;; part 2 - what comes after the dot (if anything)
- (is-primitive (cscomp-map-primitive-type p1))
- (is-local-var (and (not is-primitive) (cscomp-qualify-local-var
p1)))
- (is-instance-var (and (not is-primitive)
- (not is-local-var)
- (cscomp-qualify-instance-var p1)))
- (is-func (string-match "($" p2)) ;; p2 ends in open-paren
- (is-ctor (and ;; constructor of bare type?
- (null p1)
- (eq 0 (string-match cscomp--new-regexp p2))))
- cflavor p1-type is-static r)
-
-
- ;; figure out what we're completing on.
-
- (cond
- (is-ctor
- (cscomp-log 3 "find-completion-for-split: is-ctor")
- ;; user may be asking for completions on:
- ;; - a namespace name
- ;; - a type name within a namespace
- ;; - a constructor. This is sort of like a type name except,
- ;; the p2 token ends in an open-paren.
- (setq cflavor (if is-func "ctors" "namespace")
- p2 (substring p2 (match-beginning 2)) ;; trim the "new"
- split (cscomp-split-by-dots p2)
- p1 (car split)
- p2 (cadr split)))
-
- (is-primitive
- ;; A method/prop/field on a byte, int, char, etc.
- (cscomp-log 3 "find-completion-for-split: is-primitive")
- (setq cflavor "type"
- p1-type is-primitive
- is-static t)) ;; get static methods/props/fields on System.Byte,
etc
-
- (is-local-var
- ;; looking for a completion (method, property, or field) on a local
variable.
- (cscomp-log 3 "find-completion-for-split: is-local-var %s"
(prin1-to-string is-local-var))
- (setq cflavor "type"
- p1-type (or (cscomp-map-primitive-type (car is-local-var))
- (car is-local-var))))
-
- (is-instance-var
- ;; it's an instance variable.
- (cscomp-log 3 "find-completion-for-split: is-instance-var")
- (setq cflavor "type"
- p1-type (or (cscomp-map-primitive-type (car is-instance-var))
- (car is-instance-var))))
-
- ((string= "this" p1)
- ;; complete on instance field/prop/method
- (setq cflavor "this"))
-
- ;;; this can never happen.
- ;;;
- ;; ((and (null p1) ;; no prefix.
- ;; is-func) ;; open paren is the last char, eg "new TimeSpan(?"
- ;; (setq r (cscomp-qualify-name (substring p2 0 -1)))
- ;; (cond ((listp r)
- ;; (if (string= (car r) "type")
- ;; (setq cflavor "namespace" ;; TODO: verify correctness
- ;; p1-type (and
- ;; (string-match "^\\(.+\\)\\..+$" (cadr r))
- ;; (match-string 1 (cadr r)))
- ;; p1 p1-type)
- ;; (setq cflavor "local")))
- ;; (t
- ;; (setq cflavor "local"))))
-
- ((null p1) ;; no prefix
- (cond
- (is-func
- (error "not sure what to do here."))
- (t
- (setq cflavor (if (or (not p2) (string= p2 ""))
- "nothing" ;; nothing to do
- "mixed")))))
-
- (t
- (setq r (cscomp-qualify-name p1))
- (cond
- ((listp r)
- (progn
- (setq cflavor (car r))
-
- (if (string= cflavor "unknown")
- ;; assume p1 is an expression. Try to infer the type.
- (let ((inferred-type-info
- (cscomp-infer-type-of-expression p1)))
-
- (if inferred-type-info
- (setq p1-type
- (or (cscomp-map-primitive-type (car
inferred-type-info))
- (car inferred-type-info))
- cflavor "type")))
-
- ;; name qualification was successful
- (setq p1-type p1
- is-static t)))) ;; if it's a type, we want static f/m/p only
-
- (t
- (error "qualify-name returns invalid results.")))))
-
-
- (cscomp-log 2 "find-completion-for-split: B: p1(%s,%s) p2(%s) flav(%s)"
- p1 (if p1 p1-type "--") (prin1-to-string p2) cflavor)
-
- (if (and reuse-results
- cscomp-current-list
- (and cscomp-current-flavor (string= cflavor
cscomp-current-flavor))
- (and cscomp-current-p1 (string= p1 cscomp-current-p1))
- (and cscomp-current-p2 (cheeso-string-starts-with p2
cscomp-current-p2)))
- (progn
- (setq cscomp-current-p2 p2)
- (cscomp-log 2 "find-completion-for-split: re-using previous result
(%s %s)"
- p1 p2)
- cscomp-current-list)
-
- (progn
- ;; store these for future use
- (setq cscomp-current-p1 p1
- cscomp-current-p2 p2
- cscomp-current-flavor cflavor)
-
- ;; now collect completion options depending on the "flavor" of
- ;; completion request:
- ;;
- ;; type - completing on m/f/p for a type, possibly with a fragment.
- ;; p1 holds the typename from the buffer, could be partially
- ;; qualified, in other words it might include a namespace.
- ;; p1-type holds the fully qualified type name. p2 holds the
- ;; fragment that will be completed.
- ;;
- ;; namespace - completing on a namespace. The result can be a child
- ;; namespace or a type within a namespace. When this is the case,
- ;; p1 holds the qualifying namespace if any, and p2 holds the type
- ;; or ns name fragment to complete on.
- ;;
- ;; ctors - completing on type constructors. p1 holds any qualifying
- ;; ns, and p2 holds the typename (or ctor name, which is the same
- ;; thing).
- ;;
- ;; this - completing on a m/f/p of the local instance
- ;;
- ;; local - completing on a m/f/p of local variables or method args
- ;;
-
- ;; Reset the completion list - the thing that is used
- ;; when the "no menu" version of complete-at-pont is used.
- (setq cscomp-current-list nil)
-
- (cscomp-log 2 "find-completion-for-split, flav(%s)" cflavor)
-
- (cond
-
- ((string= cflavor "type")
- (let* ((type-info (cscomp-get-typeinfo p1-type))
- (full-list (cscomp-completion-list-for-type type-info)))
- (cond
-
- (is-func ;; it's a specific function on a type. Get the list of
overloads.
- (setq cscomp-current-list
- (cscomp-find-all-type-completions (substring p2 0 -1)
full-list is-static))
- (cscomp-log 3 "find-completion-for-split: [%s]"
- (prin1-to-string cscomp-current-list)))
- (t ;; could be anything: method, prop, field. Build the list.
- (setq cscomp-current-list
- (cscomp-find-all-type-completions p2 full-list is-static))
-
- (cscomp-log 3 "find-completion-for-split: [%s]"
- (prin1-to-string cscomp-current-list))))))
-
-
- ((string= cflavor "namespace")
- (cscomp-log 2 "find-completion-for-split is-func(%s) bot(%d)"
- is-func beginning-of-token1)
-
- ;;(if is-ctor
- ;; provide type names, or child namespaces
- (let ((namespaces-to-scan
- (if (null p1)
- ;; search for completions in any of the implicit
- ;; namespaces: any imported via using clauses, plus
- ;; the ambient namespace.
- ;;
- ;; TODO: add types and child ns for the ambient
- ;; namespace.
- (cscomp-referenced-assemblies)
- ;; else, search only in the explicitly
- ;; provided ns.
- (list p1))))
-
- (loop
- for x in namespaces-to-scan do
- (progn
- (cscomp-load-one-assembly x)
- (let* ((nsinfo
- (cscomp-get-completions-for-namespace x))
- (full-list
- (cscomp-completion-list-for-ns nsinfo)))
-
- (setq cscomp-current-list
- (append cscomp-current-list
- (cscomp-find-all-ns-completions p2
full-list))))))
-
- (cscomp-log 3 "ctors: [%s]"
- (prin1-to-string cscomp-current-list)))
-
- ;;(error "find-completion-for-split: bad state"))
- )
-
-
- ((string= cflavor "ctors")
- (let* ((short-name (substring p2 0 -1))
- (type-name (if (stringp p1)
- (concat p1 "." short-name)
- (cscomp-qualify-type-name short-name)))
- (ctor-info (cscomp-get-type-ctors type-name))
- (full-list (cscomp-completion-list-for-ctors ctor-info)))
-
- ;; present all constructors
- (setq cscomp-current-list full-list)))
-
-
- ;; (cond
- ;; (is-func ;; it's a function on a type - see if a constructor
- ;; (cond
- ;; ((save-excursion
- ;; (goto-char beginning-of-token1)
- ;; (re-search-backward "\\<new[ \t\n\f\v]+" nil t))
- ;; ;; it's a constructor
- ;; (let* ((type-name (concat p1 "." (substring p2 0 -1)))
- ;; (ctor-info (cscomp-get-type-ctors type-name))
- ;; (full-list (cscomp-completion-list-for-ctors
ctor-info)))
- ;;
- ;; ;; present all constructors
- ;; (setq cscomp-current-list full-list)))
- ;;
- ;; (t
- ;; ;; not a constructor. Must be some other function.
- ;; (error "completion on static functions is not (yet?)
supported."))))
- ;;
- ;; (t
-
- ;; $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
-
- ((string= cflavor "local")
- (let ((instance-vars (cscomp-matching-instance-vars p2))
- (locals (cscomp-matching-local-vars p2)))
- (setq cscomp-current-list
- (nconc instance-vars locals))))
-
- ((string= cflavor "this")
- (setq cscomp-current-list
- (cscomp-matching-instance-members p2)))
-
- ((string= cflavor "mixed")
- (setq r (cscomp-get-all-known-matches p2))
- (if (listp r)
- (setq cscomp-current-list
- (mapcar '(lambda (listitem)
- (list
- ;; the thing to return when this menu item is
selected
- (cond
- ((string= "type" (car listitem))
- (if (and p1 (string-match (concat "^" p1)
- (cadr listitem)))
- (cadr listitem)
- (string-match (concat "\\.\\(" p2 ".*\\)")
(cadr listitem))
- (match-string 1 (cadr listitem))))
-
- (t
- ;;(string-match (concat "\\.\\(" p2 ".*\\)")
(cadr listitem))
- (string-match (concat "^\\(" p2 ".*\\)")
(cadr listitem))
- (match-string 1 (cadr listitem))))
-
- ;; the description that will be visible in the
menu
- ;; for this menu item.
- (if (eq (length listitem) 3)
- (nth 2 listitem)
- (concat (cadr listitem) " | (" (car
listitem) ")"))))
- r))
-
- (error "Cannot complete.")))
-
- ((string= cflavor "nothing")
- (message "Nothing to complete."))
-
- (t
- (cscomp-log 1 "find-completion-for-split, unknown flavor (%s)"
- cflavor)
- (error "Cannot complete.")))))))
-
-
-
-
-
-;; (defun cscomp-string-starts-with (s arg)
-;; "returns t if string S starts with ARG. Else nil."
-;; (eq 0 (string-match arg s)))
-
-
-
-(defun cscomp-yasnippet-for-arglist (method-name arglist)
- "Produce a snippet that's usable with ya-snippet, for the method
-selected from the completion popup menu. The arguments are strings:
-METHOD-NAME is the name of the method, and ARGLIST is a description
-of the argument list for the selected method.
-
-The return value is a list, which, if selected from the menu, will be
-eval'd. The first element in the list is the literal, yas/expand-snippet,
-and subsequent elements in the return value list are simply arguments
-to that function.
-
-"
- (let ((template "(") (str-ix 1) (arg-ix 1)
- (next-char (char-after))
- need-delete)
-
- ;; Build the template for yasnippet. Each replaceable
- ;; param is identified with ${N:foo} where N is 1,2,3...
- ;; and foo is the placeholder shown in the buffer, which
- ;; is then "typed over" by the user.
- ;;
- ;; In this case, the placeholder contains the type and the
- ;; name of the argument, from the reflection results.
- ;;
- (while (string-match "\\([^ ]+\\) \\([^,)]+\\)\\([,)]\\)"
- arglist str-ix)
- (setq template (concat template "${"
- (number-to-string arg-ix)
- ":"
- ;; type of the arg
- (substring arglist
- (match-beginning 1)
- (match-end 1))
- " "
- ;; name of the arg
- (substring arglist
- (match-beginning 2)
- (match-end 2))
- "}"
-
- ;; the following comma or closing paren
- (if (string= (substring arglist
- (match-beginning 3)
- (match-end 3))
- ")")
- ;; If a close-paren is in the buffer,
- ;; cscomp will delete it, before inserting
- ;; the snippet.
- (progn
- ;; to delete the existing close paren
- (setq need-delete (eq next-char 41))
- ")")
- ", "))
-
- str-ix (match-end 0)
- arg-ix (1+ arg-ix)))
-
- (if (eq (length template) 1)
- (setq template "()"))
-
- ;; Upon selection of this item from the menu, emacs will
- ;; call yas/expand-snippet. If necessary, emacs will
- ;; delete a char just before doing so.
- (if need-delete
- (list 'progn
- (list 'delete-char '1)
- (list 'yas/expand-snippet '(point) '(point)
- (concat method-name template)))
- (list 'yas/expand-snippet '(point) '(point)
- (concat method-name template)))))
-
-
-
-
-(defun cscomp-get-menu-item-for-clist-item (clist-item)
- "Produce a menu item for the item on the completion list.
-
-The incoming CLIST-ITEM is one item from the completion list; it
-is either a (NAME DESCRIP) pair, or a simple NAME.
-
-The return value is a menu item - a thing suitable for use within
-a popup menu. It is a 2-member cons cell, the first member is a
-string to be displayed, the second is the value returned when
-that menu item is selected.
-
-This value is returned to logic in
-`cscomp-popup-completion-menu', and can be anything. That
-fn follows a convention that if the return value is a string, the
-string is inserted. If the return value is a list, as with
-ya-snippet, the list is eval'd and the result is inserted.
-
-This fn simply transforms the simple (NAME DESCRIP) pair into
-something suitable for use within a menu.
-
-"
- (if (consp clist-item)
- (let ((mpfv-name (car clist-item)) ;; name of method, prop, field,
variable
- (descrip (cscomp-fix-generics-in-descrip-line (cadr clist-item))))
-
- (cond
-
- ((string-match "(\\(Method\\|Constructor\\))[^(]+\\(([^)]*)\\)"
descrip)
- ;; It's a method or constructor. The value returned when this
- ;; menu item is selected is a cons cell that will be eval'd.
- ;; The cons is a call to yas/expand-snippet that will insert a
- ;; template for the (possibly empty) arglist of the selected
- ;; method or constructor.
- (let ((arglist (substring descrip
- (match-beginning 2)
- (match-end 2)))
- ;; for ctor, insert the short name.
- (name-to-insert (if (string= (substring descrip
- (match-beginning 1)
- (match-end 1))
- "Constructor")
- (if (string-match ".+\\." mpfv-name)
- (substring mpfv-name
- (match-end 0))
- mpfv-name)
- mpfv-name)))
-
- (cons (concat mpfv-name " | " descrip)
- (if (fboundp 'yas/expand-snippet)
- (cscomp-yasnippet-for-arglist name-to-insert arglist)
- (concat name-to-insert arglist)))))
-
- (t
- ;; The completion is not a method - just
- ;; insert the name of the field/prop as a string.
- (cons (concat mpfv-name " | " descrip)
- mpfv-name))))
-
- (cons clist-item clist-item)))
-
-
-
-(defun cscomp-popup-completion-menu (title)
- "Popup a completion menu for the object at point. The popup
-menu displays all of the possible completions for the object it
-was invoked on.
-
-TITLE is the title presented. The contents of the menu are provided
-in `cscomp-current-list' .
-
-"
-
- ;; cscomp-current-list holds the completion list.
- ;;
- ;; For a type, the clist gets methods, properties and fields.
- ;; Each element in the list is a list, (NAME DESCRIP), where NAME
- ;; is the name of the method/prop/field, and DESCRIP is a string
- ;; description.
- ;;
- ;; For a namespace, the clist is a list of strings, names
- ;; of types or child namespaces. (I think this is still true)
- ;;
- ;; In each case we want to sort the list alphabetically.
- ;;
-
- (let* ((menu-map (cons "ignored"
- (mapcar 'cscomp-get-menu-item-for-clist-item
- cscomp-current-list)))
- (menu-result (cscomp--popup-menu
- (list (or title "Completions...") menu-map))))
-
- (cscomp-log 1 "menu-result: %s" (prin1-to-string menu-result))
-
- ;; now, handle the selection
- (cond
- ((consp menu-result)
- (delete-region cscomp-current-beginning cscomp-current-end)
- (eval menu-result) ;; maybe a snippet expansion
- "")
-
- ((numberp menu-result) (number-to-string menu-result))
-
- ((null menu-result) "")
-
- (t menu-result)))) ;; a simple string
-
-
-
-
-
-
-;; To do thie yasnippet thing for methods/params:
-;;
-;; (defun dox ()
-;; "expand a template"
-;; (interactive)
-;; (let ((template
-;; "this is ${1:index} the expanded template ${2:foo}"
-;; ))
-;; (yas/expand-snippet (point) (point) template)))
-
-
-
-
-(defun cscomp-selected-frame ()
- (if (fboundp 'window-edges)
- (selected-frame)
- (selected-window)))
-
-
-(defun cscomp-current-row ()
- "Return current row number in current frame."
- (if (fboundp 'window-edges)
- (+ (car (cdr (window-edges))) (count-lines (window-start) (point)))
- (count-lines (window-start) (point))))
-
-
-(defun cscomp-get-point-pixel-pos ()
- "Return point position in pixels: (x, y)."
- (let ((mouse-pos (mouse-position))
- (pixel-pos nil)
- (ret nil))
- (if (car (cdr mouse-pos))
- (progn
- ;; set mouse position
- (set-mouse-position (cscomp-selected-frame) (current-column)
(cscomp-current-row))
- ;; inquire mouse position
- (setq pixel-pos (mouse-pixel-position))
- ;; restore mouse position
- (set-mouse-position (car mouse-pos) (car (cdr mouse-pos)) (cdr (cdr
mouse-pos)))
-
- (setq ret (list (+ (cadr pixel-pos) 40) (cdr (cdr pixel-pos)))))
- (progn
- (setq ret '(0 0))))
- (cscomp-log 3 "mouse pos is %s" ret)
- ret))
-
-
-(defun cscomp-posn-at-point-as-event (&optional position window dx dy)
- "Return pixel position of top left corner of glyph at POSITION,
-relative to top left corner of WINDOW, as a mouse-1 click
-event (identical to the event that would be triggered by clicking
-mouse button 1 at the top left corner of the glyph).
-
-POSITION and WINDOW default to the position of point in the
-selected window.
-
-DX and DY specify optional offsets from the top left of the glyph."
- (unless window (setq window (selected-window)))
- (unless position (setq position (window-point window)))
- (unless dx (setq dx 0))
- (unless dy (setq dy 0))
-
- (let* ((pos (posn-at-point position window))
- (x-y (posn-x-y pos))
- (edges (window-inside-pixel-edges window))
- (win-x-y (window-pixel-edges window)))
- ;; adjust for window edges
- (setcar (nthcdr 2 pos)
- (cons (+ (car x-y) (car edges) (- (car win-x-y)) dx)
- (+ (cdr x-y) (cadr edges) (- (cadr win-x-y)) dy)))
- (list 'mouse-1 pos)))
-
-
-(defun cscomp--popup-menu (menu-data)
- "Pop up the completion menu at point, using the data MENU-DATA.
-MENU-DATA is a list of error and warning messages returned by
-`cscomp-make-err-menu-data'."
- (if (featurep 'xemacs)
- (let* ((pos (cscomp-get-point-pixel-pos))
- (x-pos (nth 0 pos))
- (y-pos (nth 1 pos))
- (event-props '(button 1 x 1 y 1)))
- (setq event-props (plist-put event-props 'x x-pos))
- (setq event-props (plist-put event-props 'y y-pos))
- (popup-menu (cscomp-make-xemacs-menu menu-data)
- (make-event 'button-press event-props)))
- (x-popup-menu (if (eval-when-compile (fboundp 'posn-at-point))
- (cscomp-posn-at-point-as-event nil nil 42 20)
- (list (cscomp-get-point-pixel-pos) (selected-window)))
- menu-data)))
-
-
-
-
-(defun cscomp-cycle-candidates ()
- "Replace the previous completion by the next one in
-`cscomp-current-list'. Uses `cscomp-current-list-index'
-to track the position in the list, and markers `cscomp-current-end'
-and `cscomp-current-beginning' to track the position in the
-buffer.
-
-The elements in `cscomp-current-list' can be either lists, or
-atoms. In the case of completing on a namespace (eg, start with System.Co),
-the completion list will contain strings. (CodeDom, Console,Collections...).
-
-If completing on a type or instance, the list elems are 2-element lists -
-the car is the thing to insert, and the cadr is a description of the thing.
-is it a property, method, field? what is the return type? if a method,
-then what arguments does it require? The cadr is used only in the menu,
-not in the inserted text.
-
-On the first entry in this function, the markers record the beginning and
-end of the fragment being completed. (eg, Co if completing on System.Co).
-On exit, the markers record the beginning and end of what has been inserted.
-On subsequent entry, it retains those values. On all entries, this fn
-deletes the text between the markers, before inserting the completion.
-
-"
- (let (elem)
- (incf cscomp-current-list-index)
- (cscomp-log 3 "list index: %d" cscomp-current-list-index)
- (if (>= cscomp-current-list-index (length cscomp-current-list))
- (setq cscomp-current-list-index 0)) ;; rollover
- (setq elem (nth cscomp-current-list-index cscomp-current-list))
-
- (cscomp-log 3 "complete-cycle-candidates: looking at %s" (prin1-to-string
elem))
-
- (cond
-
- ((listp elem)
- (let ((thing-to-insert (car elem)))
- (if thing-to-insert
- (progn
- (delete-region cscomp-current-beginning cscomp-current-end)
- (insert thing-to-insert)
- (set-marker cscomp-current-end
- (+ (marker-position
- cscomp-current-beginning) (length
thing-to-insert)))
- ;; display the description of the completioni n the minibuffer
- (message "cscomp: %s" (cadr elem)))
-
- (cscomp-log 1 "No completion at this point! (cycle)"))))
-
- ;; elem is an atom
- (t
- (let ((thing-to-insert elem))
- (delete-region cscomp-current-beginning cscomp-current-end)
- (insert thing-to-insert)
- (set-marker cscomp-current-end
- (+ (marker-position cscomp-current-beginning) (length
thing-to-insert) ))
- ;; display the description of the completioni n the minibuffer
- (message "cscomp: %s" elem))))))
-
-
-
-(defun cscomp-complete-at-point ()
- "Completes at point. Performs completion on field, prop or
-method names if the thing being completed is a type or instance,
-or on namespace members - child namespaces or types - if the
-thing being completed is a namespace.
-
-This function is interactive.
-
-Invoking this fn multiple times in succession cycles through the
-completions.
-
-On first entry, it finds the completion, by calling out to the
-CscompShell by calling `cscomp-find-completion-for-split'.
-It then caches the resulting list of completion options into
-`cscomp-current-list'.
-
-On subsequent entry, it uses the cached results. After inserting a
-completion, this function displays the signature of a method completion
-in the minibuffer.
-
-This fn starts the Cscompshell if necessary. Hence, you may
-experience a slight delay when using this command for the first
-time in a session or when completing a field or method of an
-object that has many methods and fields.
-
-See `cscomp-complete-at-point-menu' for an alternative to this command
-that lets you select the desired completion from a popup menu.
-"
-
- (interactive)
-
-;; This command uses the Cscompshell to run Csharp code that in turn uses
-;; .NET reflection to determine the methods, properties, and fields
-;; defined by the type of the object at point.
-
- (if (and
- cscomp-current-list
- (eq last-command this-command)
- (markerp cscomp-current-beginning)
- (markerp cscomp-current-end)
- (marker-position cscomp-current-beginning)
- (marker-position cscomp-current-end)
- (>= (point) (marker-position cscomp-current-beginning))
- (eq (point) (marker-position cscomp-current-end)))
-
- ;; we've got a completion list. cycle through the items.
- (cscomp-cycle-candidates)
- ;; no completion list available. get one.
- (progn
- (let* ((parse-result (cscomp-parse-csharp-expression-before-point))
- (split (and parse-result (cadr parse-result))))
-
- (if (not (null split))
- (progn
- (cscomp-find-completion-for-split split (car parse-result))
- (setq cscomp-current-list-index -1)
- (cscomp-cycle-candidates)))))))
-
-
-
-(defun cscomp-complete-at-point-menu ()
- "Pops up a menu with a list of completions for point. When completing
-on a type or instance, the menu items are the field, property and method
-names; when completing on a namespace, the menu items are child namespaces
-or types.
-
-When the user makes a selection from the menu, the selected item
-is inserted at point. In the case of a method with parameters,
-and when yasnippet.el is available (see
-http://code.google.com/p/yasnippet/), the inserted thing is a
-parameterized snippet, a template that can then be filled in by
-the user. If yasnippet is not available, then the user's menu
-choice is just inserted into the buffer as static text.
-
-See `cscomp-complete-at-point' for an alternative to this function that
-lets you cycle through the potential completions at point, with each
-completion appearing in the buffer in turn.
-
-"
- (interactive)
- (let* ((parse-result (cscomp-parse-csharp-expression-before-point))
- (split (and parse-result (cadr parse-result))))
-
- (if (not (null split))
- (progn
- (cscomp-find-completion-for-split split (car parse-result))
-
- (if cscomp-current-list
- (let* ((title (if (car split)
- (concat (car split) "."
- (cadr split) "...")
- (concat (cadr split) "...")))
- (selection (cscomp-popup-completion-menu title)))
- (if (and selection
- (not (string= selection "")))
- (progn
- (delete-region cscomp-current-beginning
cscomp-current-end)
- (insert selection)
- )))
- (message "No completion at this point.")))
- (message "No completion at this point."))))
-
-
-
-
-;; ========================================================================
-;; integration with Matsuyama's auto-complete.el
-
-(defun cscomp-completions-at-point ()
- "Generates completions of field, prop or method names if the
-thing being completed is a type or instance, or on namespace
-members - child namespaces or types - if the thing being
-completed is a namespace.
-
-The result is a list of strings.
-
-This fn is used by Matsuyama's auto-complete.el, when using
-csharp-completion as a source.
-
-See also `cscomp-complete-at-point-menu' and `cscomp-complete-at-point'
-for interactive functions that do, just about the same thing.
-"
- (progn
- (let* ((parse-result (cscomp-parse-csharp-expression-before-point))
- (split (and parse-result (cadr parse-result))))
-
- (if (not (null split))
- (progn
- (cscomp-find-completion-for-split split (car parse-result) t)
-
- (mapcar
- ;; I thought I needed a separate lambda when the p1
- ;; was non-nil, but maybe that is not the case.
- (if cscomp-current-p1
- '(lambda (item)
- ;;(cscomp-log 3 "considering item: %s" item)
- (let ((result
- (car item)
- ;;(concat cscomp-current-p1 "." (car item))
- ))
- ;;(cscomp-log 3 "result: %s" result)
- result))
-
- '(lambda (item)
- ;;(cscomp-log 3 "considering item: %s" item)
- (car item)))
-
- cscomp-current-list))
- nil))))
-
-
-;; (eval-after-load "auto-complete"
-;; '(progn
-;; (if (fboundp 'ac-candidates-1)
-;; (progn
-;; ;; In lieu of using the ac-define-source macro,
-;; ;; define the function and the var separately.
-;; (defvar ac-source-csharp
-;; '((init . (setq cscomp-current-list nil))
-;; (candidates . cscomp-completions-at-point)
-;; (cache)))
-;;
-;; (defun ac-complete-csharp ()
-;; (interactive)
-;; (auto-complete '(ac-source-csharp)))))))
-
-
-
-;; In lieu of using the ac-define-source macro,
-;; define the function and the var separately.
-(defvar ac-source-csharp
- '((init . (setq cscomp-current-list nil))
- (candidates . cscomp-completions-at-point)
- (cache)))
-
-
-(defun ac-complete-csharp ()
- "performs auto-completion using the source `ac-source-csharp'."
- (interactive)
- (auto-complete '(ac-source-csharp)))
-
-
-(provide 'csharp-completion)
-
-;;; end of csharp-completion.el
diff --git a/csharp-shell.el b/csharp-shell.el
deleted file mode 100644
index 0e4afbb..0000000
--- a/csharp-shell.el
+++ /dev/null
@@ -1,417 +0,0 @@
-;;; csharp-shell.el --- run PowerShell to assist with c# completion.
-;;
-;; Author : Dino Chiesa <dpchiesa@hotmail.com>
-;; Created : 10 Apr 2008
-;; Modified : February 2011
-;; Version : 0.2
-;; Keywords : powershell C# shell
-;; Last-saved : <2011-March-01 12:56:20>
-;; X-URL : ??
-;;
-
-;;; Commentary:
-;;
-;; This is code that provides an emacs shell that supports C#
-;; code-completion. It depends on Powershell.el, which depends on
-;; shell.el. This module is part of cscomp, a C# completion package.
-;;
-;; csharp-shell.el is responsible for starting a PowerShell shell, and
-;; loading a utility assembly, also part of CsComp, into it. The
-;; running shell can be used as a regular, interactive powershell
-;; shell, but its primary purpose is to connect elisp to the .NET
-;; assembly that performs reflection.
-;;
-;; When the user requests completion on a variable (etc), logic within
-;; csharp-completion.el sends a command to the CscompShell, and gets the
-;; response, in the form of a lisp s-expression. The logic in
-;; csharp-completion.el then evals that sexp, and does something
-;; intelligent with the result.
-;;
-;; The two main public interfaces for this module are:
-;;
-;; `csharp-shell-exec-and-eval-result'
-;; `csharp-shell-exec-and-maybe-eval-result'
-;;
-;;
-;; Some History:
-;; idea of CSDE, the C# Development Environment, was initially
-;; conceived by Matt Bruce in 2001 (or so), and ported from JDE, the
-;; Java Development Environment.
-;;
-;; But the ambitious vision of CSDE was never completed. The latest
-;; version is aparently still available on sourceforge, but it was
-;; never updated or maintained. <URL:http://www.sourceforge.com/>.
-;;
-;; Rather than start with "everything", I thought I'd start by
-;; producing a module that did one thing well: code completion. This
-;; is something like what is known as Intellisense in Microsoft's
-;; Visual Studio.
-;;
-;; To do this, I didn't keep any of the old CSDE code. I kept only the
-;; idea of code completion, as well as the idea of using an external
-;; shell to aid in dynamic type and symbol resolution. This is all
-;; new code.
-;;
-;; ------------
-;;
-;; Please send any comments, bugs, or upgrade requests to
-;; Dino Chiesa (dpchiesa@hotmail.com)
-;;
-
-
-(require 'cscomp-base)
-(require 'powershell)
-
-(defcustom csharp-shell-location-of-util-dll nil
- "Folder name that contains the Cscomp DLL for C# Completion.
-Set this to nil, to load the DLL named CscompUtilities.dll from
-the same directory where csharp-shell.el is located.
-
-Otherwise, set it to a fully-qualified path of a directory that contains
-the file cscompUtilities.dll. It should use fwd-slashes and should include
-the trailing slash. For example,
-
- \"c:/users/fred/elisp/cscomp/\"
-
-"
- :group 'cscomp
- :type 'string)
-
-(defcustom csharp-shell-startup-timeout 20
- "*Length of time the CSharpShell waits for the shell process to startup.
-Increase the value of this variable if you get Lisp errors
-on Shell startup."
- :group 'cscomp
- :type 'integer)
-
-(defcustom csharp-shell-exec-timeout 5
- "*Length of time in seconds to wait for the CscompShell to respond to
commands
-before giving up and signaling an error. This isn't the total timeout; it's
-the time to wait between chunks of response. "
- :group 'cscomp
- :type 'integer)
-
-(defcustom csharp-shell-buffer-name "*CscompShell*"
- "Name of the Powershell buffer for C# completion support."
- :group 'cscomp
- :type 'string
- )
-
-(defconst csharp-shell-prompt-string "CscompShell % "
- "The prompt string used for csharp-shell. It is also used as a regex, so
this string must contain no regex-sensitive sequences. Best to just leave it
alone.")
-
-
-
-
-
-(defun csharp-shell-exec-and-maybe-eval-result (expr &optional eval-return)
- "Sends EXPR to the CscompShell. EXPR could theoretically be
-any valid Powershell command, but this fn is invoked from
-csharp-completion, the EXPR is a call to static function in the
-CscompUtilities.dll assembly.
-
-If the shell is not already running, this function starts
-it. Collects the text output from the shell. If the optional
-argument EVAL-RETURN is non-nil, this function returns the result
-of evaluating the output as a Lisp expression. Otherwise, the
-return value is the collected text.
-"
- (let ((proc
- (or (get-buffer-process csharp-shell-buffer-name)
- (let (proc2)
- (csharp-shell--internal)
- (setq proc2 (get-buffer-process csharp-shell-buffer-name))
- proc2))))
-
- (if proc
- (let (reply tmp)
-
- (with-current-buffer csharp-shell-buffer-name
- (cscomp-log 3 "csharp-shell-exec: Sending: %s" expr)
- (setq reply
- (powershell-invoke-command-silently proc expr
csharp-shell-exec-timeout)))
-
-
- (cond ((null reply)
- (with-current-buffer csharp-shell-buffer-name
- (cscomp-log 3 "csharp-shell-exec: Sending newline" expr)
- (setq reply
- (powershell-invoke-command-silently proc "\n"
csharp-shell-exec-timeout)))))
-
-
- (cond
- ((string-match "// Error:" reply)
- (progn
- (cscomp-log 0
- "csharp-shell-exec: CscompShell command error.\n
Expression: %s\n Error: %s"
- expr reply)
- (error "CscompShell eval error. See messages buffer for
details."))))
-
-
- (if eval-return
- (if (and reply (not (string= reply "")))
- (progn
- (cscomp-log 3 "csharp-shell-exec: evaluating reply: '%s'"
reply)
-
- (setq tmp (read reply)) ;; get one s-exp
- (if (not (eq tmp "CscompShell")) ;; means no response at
all
-
- (progn
- (setq tmp (eval tmp))
- (cscomp-log 3 "csharp-shell-exec: eval result(%s)"
(prin1-to-string tmp)) ;; can be nil
- tmp)
- nil))
-
- ;; else
- (progn
- (cscomp-log 1 "csharp-shell-exec: result is empty. Will not
evaluate.")
- nil))
-
- ;; else (no eval)
- (progn
- (cscomp-log 1 "csharp-shell-exec: no eval, reply: '%s'" reply)
- reply))))))
-
-
-
-
-
-
-(defun csharp-shell-exec-and-eval-result (psh-statement)
- "Convenience function for evaluating Powershell statements
-that return Lisp expressions as output. This function
-invokes `csharp-shell-exec-and-maybe-eval-result' with the
-evaluate-return option set to t.
-"
-
- (csharp-shell-exec-and-maybe-eval-result psh-statement t))
-
-
-
-
-;; ;; dinoch - Thu, 20 May 2010 14:59
-;; ;;
-;; ;; TODO: now I cannot remember why this is here. Do I need to explicitly
-;; ;; override the shell function? Must check this.
-;;
-;; (defun shell (&optional buffer)
-;; "Run an inferior shell, with I/O through BUFFER (which defaults to
`*shell*').
-;; Interactively, a prefix arg means to prompt for BUFFER.
-;; If BUFFER exists but shell process is not running, make new shell.
-;; If BUFFER exists and shell process is running, just switch to BUFFER.
-;; Program used comes from variable `explicit-shell-file-name',
-;; or (if that is nil) from the ESHELL environment variable,
-;; or (if that is nil) from `shell-file-name'.
-;; If a file `~/.emacs_SHELLNAME' exists, or `~/.emacs.d/init_SHELLNAME.sh',
-;; it is given as initial input (but this may be lost, due to a timing
-;; error, if the shell discards input when it starts up).
-;; The buffer is put in Shell mode, giving commands for sending input
-;; and controlling the subjobs of the shell. See `shell-mode'.
-;; See also the variable `shell-prompt-pattern'.
-;;
-;; To specify a coding system for converting non-ASCII characters
-;; in the input and output to the shell, use
\\[universal-coding-system-argument]
-;; before \\[shell]. You can also specify this with
\\[set-buffer-process-coding-system]
-;; in the shell buffer, after you start the shell.
-;; The default comes from `process-coding-system-alist' and
-;; `default-process-coding-system'.
-;;
-;; The shell file name (sans directories) is used to make a symbol name
-;; such as `explicit-csh-args'. If that symbol is a variable,
-;; its value is used as a list of arguments when invoking the shell.
-;; Otherwise, one argument `-i' is passed to the shell.
-;;
-;; \(Type \\[describe-mode] in the shell buffer for a list of commands.)"
-;; (interactive
-;; (list
-;; (and current-prefix-arg
-;; (read-buffer "Shell buffer: "
-;; (generate-new-buffer-name "*shell*")))))
-;; (setq buffer (get-buffer-create (or buffer "*shell*")))
-;; ;; Pop to buffer, so that the buffer's window will be correctly set
-;; ;; when we call comint (so that comint sets the COLUMNS env var properly).
-;; (pop-to-buffer buffer)
-;; (unless (comint-check-proc buffer)
-;; (let* ((prog (or explicit-shell-file-name
-;; (getenv "ESHELL") shell-file-name))
-;; (name (file-name-nondirectory prog))
-;; (startfile (concat "~/.emacs_" name))
-;; (xargs-name (intern-soft (concat "explicit-" name "-args"))))
-;;
-;; (unless (file-exists-p startfile)
-;; (setq startfile (concat "~/.emacs.d/init_" name ".sh")))
-;; (apply 'make-comint-in-buffer "shell" buffer prog
-;; (if (file-exists-p startfile) startfile)
-;; (if (and xargs-name (boundp xargs-name))
-;; (symbol-value xargs-name)
-;; '("-i")))
-;; (shell-mode)))
-;; buffer)
-
-
-
-(defun csharp-shell--start ()
- "Run a special instance of PowerShell in support of C# Completion, by
invoking the `powershell' function. The buffer containing the shell is named
`csharp-shell-buffer-name'.
-"
-
- (let* ((cscompshell-buffer (powershell
- csharp-shell-buffer-name
- csharp-shell-prompt-string))
- (proc (get-buffer-process cscompshell-buffer))
- (dll-location (concat
- (or
- csharp-shell-location-of-util-dll
- "idontknow/" )
- "CscompUtilities.dll" ))
- result
- version)
-
- ;; xxxx
-
- (cond
- (proc
- (progn
- ;; Don't need to call save-excursion here, because
- ;; powershell has already called pop-to-buffer .
- ;; The CscompShell is the current buffer, and all
- ;; the buffer-local variables are available.
-
- ;; load the CscompUtilities DLL .
-
- (cscomp-log 2 "CscompShell: the powershell process is running...")
-
- (setq result
- (powershell-invoke-command-silently
- proc
- (concat "[System.Reflection.Assembly]::LoadFrom('" dll-location
"')")
- 6.5))
-
- (cscomp-log 2 "CscompShell: load dll result: %s" result)
-
- (if (string-match "^Exception .*: \"\\(.+\\)\"" result)
- (let ((message (substring result (match-beginning 1) (match-end
1))))
- (error (concat "error: " message))))
-
- ;; get the version number
- (setq version
- (powershell-invoke-command-silently
- proc
- "[Ionic.Cscomp.Utilities]::Version()"
- 2.9))
-
- (cscomp-log 2 "CscompShell: util dll version: %s" version)
-
- (if version
- (setq version (substring version 1 -1)))
-
- ;; If the user exits, we won't ask whether he wants to kill the
CscompShell.
- (set-process-query-on-exit-flag proc nil)
-
- ;;(comint-simple-send proc "prompt\n") ;; shouldn't need this
-
- ;; Send an initial carriage-return. The effect is to make the
- ;; prompt appear. I don't know why this is necessary here.
- ;; It's called in the powershell function, but somehow it has
- ;; no effect, when powershell is invoked from csharp-shell, so I
- ;; also call it here.
- (comint-send-input)
- (accept-process-output proc)
-
- ;; Remove the window for the shell.
- ;; shell.el automatically pops to the shell buffer, but we
- ;; don't want that in this case. For Cscomp, the shell runs unseen,
- ;; in the background. User can pop to it, if he likes.
- (delete-window)))
- (t
- (cscomp-log 2 "CscompShell: load dll result: %s" result)
- )
- )
-
- ;; return the version of the CscompUtilities.dll
- version))
-
-
-
-
-(defun csharp-shell--internal (&optional display-buffer)
- (if (not (comint-check-proc csharp-shell-buffer-name))
- (let (version)
- (cscomp-log 0 "Starting CscompShell...")
- (setq version (csharp-shell--start))
- (cscomp-log 0 "CscompShell v%s is now running..." version))
-
- (when display-buffer
- (cscomp-log 0 "CscompShell is already running."))))
-
-
-(defun csharp-shell ()
- "Starts CsharpShell, which is an instance of Powershell that loads
-a custom assembly dedicated to supporting C# code completion in emacs.
-"
- (interactive)
- (csharp-shell--internal nil)
- )
-
-
-
-
-
-(defun csharp-shell-do-shell-fn (command-string)
- "sends a string to *CscompShell*, and returns the eval'd
-result. This fn is mostly a thin wrapper around
-`csharp-shell-exec-and-eval-result' that is used for tracing
-purposes."
- (let ((result (csharp-shell-exec-and-eval-result
- (concat command-string "\n"))))
- (cscomp-log 3 "exec-and-eval (%s) result(%s)"
- command-string (prin1-to-string result))
- ;;(if (and result (listp result)) result nil)
- result
- ))
-
-
-(defun csharp-shell-escape-string-for-powershell (arg)
- "Powershell uses the backquote for an escape char. This fn
-escapes the backquote for a string that will eventually be sent
-to powershell (CscompShell).
-
-I think this is only necessary when the arg is submitted to
-powershell within double-quotes. If the arg is within single
-quotes, backquotes do not need to be escaped.
-
-I'm not really sure why I wouldn't just use single quotes in
-all cases, to avoid this entirely.
-
-"
- (let ((matcho (string-match "\\(.+\\)`\\(.+\\)" arg)))
- (if matcho
- (concat
- (substring arg (match-beginning 1) (match-end 1))
- "``"
- (substring arg (match-beginning 2) (match-end 2)))
- arg)))
-
-
-
-(defun csharp-shell-invoke-shell-fn (fn arg)
- "invokes a 1-arg CscompShell function, returns the result."
-
- ;; need to use single-quotes here around the arg, because in
- ;; some cases the arg can have double-quotes in it.
-
- (let* ((escaped-arg (csharp-shell-escape-string-for-powershell arg)))
- (csharp-shell-do-shell-fn (concat "[Ionic.Cscomp.Utilities]::" fn "(\'"
escaped-arg "\')"))))
-
-
-
-;; Set the default DLL location at load time,
-;; if appropriate.
-(or
- csharp-shell-location-of-util-dll
- (setq csharp-shell-location-of-util-dll
- (file-name-directory load-file-name)))
-
-
-(provide 'csharp-shell)
-
-;; End of csharp-shell.el
diff --git a/tfs.el b/tfs.el
deleted file mode 100644
index 4d0dd16..0000000
--- a/tfs.el
+++ /dev/null
@@ -1,554 +0,0 @@
-;;; tfs.el --- MS Team Foundation Server commands for Emacs.
-
-;; Author : Dino Chiesa <dpchiesa@hotmail.com>
-;; Version : 0.2.6
-;; X-URL :
http://cheeso.members.winisp.net/srcview.aspx?dir=emacs&file=tfs.el
-;; Last saved : <2011-May-03 10:49:03>
-;;
-;; Copyright 2009-2010 Dino Chiesa
-
-;; Microsoft Public License (Ms-PL)
-;;
-;; This license governs use of the accompanying software, the tfs.el
-;; library ("the software"). If you use the software, you accept this
-;; license. If you do not accept the license, do not use the software.
-;;
-;; 1. Definitions
-;;
-;; The terms "reproduce," "reproduction," "derivative works," and
-;; "distribution" have the same meaning here as under U.S. copyright
-;; law.
-;;
-;; A "contribution" is the original software, or any additions or
-;; changes to the software.
-;;
-;; A "contributor" is any person that distributes its contribution under
-;; this license.
-;;
-;; "Licensed patents" are a contributor's patent claims that read
-;; directly on its contribution.
-;;
-;; 2. Grant of Rights
-;;
-;; (A) Copyright Grant- Subject to the terms of this license, including
-;; the license conditions and limitations in section 3, each contributor
-;; grants you a non-exclusive, worldwide, royalty-free copyright license
-;; to reproduce its contribution, prepare derivative works of its
-;; contribution, and distribute its contribution or any derivative works
-;; that you create.
-;;
-;; (B) Patent Grant- Subject to the terms of this license, including the
-;; license conditions and limitations in section 3, each contributor
-;; grants you a non-exclusive, worldwide, royalty-free license under its
-;; licensed patents to make, have made, use, sell, offer for sale,
-;; import, and/or otherwise dispose of its contribution in the software
-;; or derivative works of the contribution in the software.
-;;
-;; 3. Conditions and Limitations
-;;
-;; (A) No Trademark License- This license does not grant you rights to
-;; use any contributors' name, logo, or trademarks.
-;;
-;; (B) If you bring a patent claim against any contributor over patents
-;; that you claim are infringed by the software, your patent license
-;; from such contributor to the software ends automatically.
-;;
-;; (C) If you distribute any portion of the software, you must retain
-;; all copyright, patent, trademark, and attribution notices that are
-;; present in the software.
-;;
-;; (D) If you distribute any portion of the software in source code
-;; form, you may do so only under this license by including a complete
-;; copy of this license with your distribution. If you distribute any
-;; portion of the software in compiled or object code form, you may only
-;; do so under a license that complies with this license.
-;;
-;; (E) The software is licensed "as-is." You bear the risk of using
-;; it. The contributors give no express warranties, guarantees or
-;; conditions. You may have additional consumer rights under your local
-;; laws which this license cannot change. To the extent permitted under
-;; your local laws, the contributors exclude the implied warranties of
-;; merchantability, fitness for a particular purpose and
-;; non-infringement.
-
-;;; Commentary:
-;;
-;; Basic steps to setup:
-;; 1. Place `tfs.el' in your `load-path'.
-;; 2. In your .emacs file:
-;; (require 'tfs)
-;; (setq tfs/tf-exe "c:\\vs2008\\common7\\ide\\tf.exe")
-;; (setq tfs/login "/login:domain\\userid,password")
-;; -or-
-;; (setq tfs/login (getenv "TFSLOGIN"))
-;; 3. also in your .emacs file:
-;; set local or global key bindings for tfs commands. like so:
-;;
-;; (global-set-key "\C-xvo" 'tfs/checkout)
-;; (global-set-key "\C-xvi" 'tfs/checkin)
-;; (global-set-key "\C-xvp" 'tfs/properties)
-;; (global-set-key "\C-xvr" 'tfs/rename)
-;; (global-set-key "\C-xvg" 'tfs/get)
-;; (global-set-key "\C-xvh" 'tfs/history)
-;; (global-set-key "\C-xvu" 'tfs/undo)
-;; (global-set-key "\C-xvd" 'tfs/diff)
-;; (global-set-key "\C-xv-" 'tfs/delete)
-;; (global-set-key "\C-xv+" 'tfs/add)
-;; (global-set-key "\C-xvs" 'tfs/status)
-;; (global-set-key "\C-xva" 'tfs/annotate)
-;; (global-set-key "\C-xvw" 'tfs/workitem)
-;;
-;;
-
-
-(defvar tfs/tf-exe "c:\\Program Files\\Microsoft Visual Studio
9.0\\common7\\ide\\tf.exe"
- "location of the tf.exe command. Defaults to \"c:\\Program Files\\Microsoft
Visual Studio 9.0\\common7\\ide\\tf.exe\"")
-
-(defvar tfs/tfpt-exe "c:\\Program Files\\Microsoft Team Foundation Server
2008 Power Tools\\TFPT.exe"
- "location of the tfpt.exe command. Defaults to \"c:\\Program
Files\\Microsoft Team Foundation Server 2008 Power Tools\\TFPT.exe\"")
-
-(defvar tfs/login "/login:domain\\user,password"
- "/login option for all TFS activity.")
-
-(defvar tfs/buffer-name "*TFS Messages*"
- "name of buffer for TFS Messages")
-
-
-
-;; -------------------------------------------------------
-;; tfs/checkout
-;; performs a TFS checkout on the file being visited by the current buffer.
-(defun tfs/checkout ()
- "Performs a tf checkout (edit) on the file being visited by the current
buffer. Checkout happens only if the file is non-writable now. In other words
checkout will fail if the local file is currently writable."
- (interactive)
- (if buffer-file-name
- (if (not (file-writable-p buffer-file-name))
- (let* ((exitcode nil)
- (shortname (file-name-nondirectory buffer-file-name))
- (command (list tfs/tf-exe "checkout" shortname)))
- (tfs/append-to-message-buffer (concat "checkout " shortname ": "
- (prin1-to-string command)
"\n"))
- (setq exitcode (apply 'call-process
- (car command)
- nil
- tfs/buffer-name
- nil
- (append (cdr command) (list tfs/login))))
- (if (equal exitcode 0)
- (let ((is-flymake-enabled
- (and (fboundp 'flymake-mode)
- flymake-mode)))
- ;; disable
- (if is-flymake-enabled
- (flymake-mode-off))
-
- ;; get the checked-out version - read from the disk file
- (revert-buffer t t)
-
- (if is-flymake-enabled
- (flymake-mode-on)))
-
- (error "Checkout of %s was unsuccessful (%S)" buffer-file-name
exitcode))))
- (error "tfs/checkout: No file")))
-
-
-
-;; -------------------------------------------------------
-;; tfs/checkin
-;; performs a TFS checkin on the file being visited by the current buffer.
-(defun tfs/checkin ()
- "perform a tf checkin on the file being visited by the current buffer.
Checkin happens only if the file is writable now. This function allows you to
specify a checkin comment. It checks in only the current file being visited -
pending changes for any other files will not be checked in."
- (interactive)
- (if buffer-file-name
- (if (file-writable-p buffer-file-name)
- (let* ((exitcode nil)
- (shortname (file-name-nondirectory buffer-file-name))
- (comment (read-string (format "Comment for %s: " shortname)
nil nil nil))
- (command (list tfs/tf-exe "checkin" (format "/comment:%s"
comment)
- buffer-file-name)))
- (tfs/append-to-message-buffer (concat "checkin " shortname ": "
- (prin1-to-string command)
"\n"))
- (setq exitcode (apply 'call-process
- (car command)
- nil
- tfs/buffer-name
- nil
- (append (cdr command) (list tfs/login))))
- (if (equal exitcode 0)
- ;; revert to the (now) readonly version
- (revert-buffer t t)
- (error "Checkin of %s was unsuccessful (%S)" buffer-file-name
exitcode)))
-
- (error "Cannot checkin %s : the file is not writable"
buffer-file-name))
- (error "tfs/checkin: No file")))
-
-
-
-;; -------------------------------------------------------
-;; tfs/rename
-;; performs a TFS rename on the file being visited by the current buffer.
-(defun tfs/rename ()
- "perform a tf rename on the file being visited by the current buffer. If
successful, it also renames the buffer to the new name.
-"
- (interactive)
- (if buffer-file-name
- (let* (
- (exitcode nil)
- (shortname (file-name-nondirectory buffer-file-name))
- (newname (read-string (format "New name for %s: " shortname) nil
nil nil))
- (command (list tfs/tf-exe "rename" shortname newname)))
- (tfs/append-to-message-buffer (concat "rename " shortname " " newname
": "
- (prin1-to-string command)
"\n"))
- (setq exitcode (apply 'call-process
- (car command)
- nil
- tfs/buffer-name
- nil
- (append (cdr command) (list tfs/login))))
- (if (equal exitcode 0)
- (set-visited-file-name newname)
- (error "Rename of %s was unsuccessful (%S)" buffer-file-name
exitcode)))
-
- (error "tfs/rename: No file")))
-
-
-
-;; -------------------------------------------------------
-;; tfs/add
-;; performs a TFS add on a file
-(defun tfs/add ()
- "perform a tf add on the file being visited by the current buffer."
- (interactive)
- (if buffer-file-name
- (let* ((shortname (file-name-nondirectory buffer-file-name))
- (command (list tfs/tf-exe "add" shortname))
- (exitcode nil))
-
- (tfs/append-to-message-buffer (concat "add " shortname ": "
- (prin1-to-string command)
"\n"))
- (setq exitcode (apply 'call-process
- (car command)
- nil
- tfs/buffer-name
- nil
- (append (cdr command) (list tfs/login))))
- (if (equal exitcode 0)
- ;; TODO: make this conditional on a verbose setting
- ;; After using this package for a while, the Add is sort of
- ;; opaque. Hard to know when it's done. It's nice to get
- ;; a confirmation message. The warm and fuzzy factor.
- (message (format "Successful add of %s" buffer-file-name))
- (error "Add of %s was unsuccessful (%S)" buffer-file-name exitcode)))
-
- (error "tfs/add: No file")))
-
-
-
-
-;; -------------------------------------------------------
-;; tfs/delete
-;; performs a TFS delete on a file.
-(defun tfs/delete ()
- "perform a tf delete on the file being visited by the current buffer. Kills
the buffer if the delete is successful."
- (interactive)
- (if buffer-file-name
- (let ((command)
- (exitcode nil)
- (shortname (file-name-nondirectory buffer-file-name)))
-
- (if (y-or-n-p (concat "Really delete " shortname "? "))
- (progn
- (setq command (list tfs/tf-exe
- "delete"
- shortname))
- (tfs/append-to-message-buffer (concat "delete " shortname ": "
- (prin1-to-string command)
"\n"))
- (setq exitcode (apply 'call-process
- (car command)
- nil
- tfs/buffer-name
- nil
- (append (cdr command) (list tfs/login))))
- (if (equal exitcode 0)
- (kill-buffer)
- (error "Delete of %s was unsuccessful (%S)" buffer-file-name
exitcode)))))
- (error "tfs/delete: No file")))
-
-
-
-
-;; -------------------------------------------------------
-;; tfs/get
-;; performs a TFS get: retrieve a readonly copy of the specified file.
-;;
-(defun tfs/get ()
- "perform a tf get on the specified file. Happens only when the file is not
writable. "
- (interactive)
- (if buffer-file-name
- (let ((command (list tfs/tf-exe "get" buffer-file-name))
- (exitcode nil)
- (shortname (file-name-nondirectory buffer-file-name)))
- (if (not (file-writable-p buffer-file-name))
- (progn
- ;;(tfs/prep-message-buffer)
- (tfs/append-to-message-buffer (concat "get " shortname ": "
- (prin1-to-string command)
"\n"))
- (setq exitcode (apply 'call-process
- (car command)
- nil
- tfs/buffer-name
- nil
- (append (cdr command) (list tfs/login))))
- (if (equal exitcode 0)
- ;; get the latest version
- (revert-buffer t t)
- (error "Get of %s was unsuccessful (%S)" buffer-file-name
exitcode)))
-
- (error "Will not get %s : the file is writable." shortname)))
- (error "tfs/get: No file")))
-
-
-;; -------------------------------------------------------
-;; tfs/undo
-;; performs a TFS undo: discards pending changes for the specified file.
Happens only when writable.
-(defun tfs/undo ()
- "perform a tf undo on the specified file. Happens only when the file is
writable. Confirms before discarding edits."
- (interactive)
- (if buffer-file-name
- (let ((command (list tfs/tf-exe "undo" buffer-file-name))
- (exitcode nil)
- (shortname (file-name-nondirectory buffer-file-name)))
- (if (file-writable-p buffer-file-name)
- (if (y-or-n-p (concat "Discard current changes for " shortname "?
"))
- (progn
- (tfs/append-to-message-buffer (concat "undo " shortname ": "
- (prin1-to-string command)
"\n"))
- (setq exitcode (apply 'call-process
- (car command)
- nil
- tfs/buffer-name
- nil
- (append (cdr command) (list
tfs/login))))
- (if (equal exitcode 0)
- ;; get the checked-out (reverted) version
- (revert-buffer t t)
- (error "undo on %s was unsuccessful (%S)"
- buffer-file-name exitcode))))
- (error "cannot undo %s : the file is not writable" shortname)))
- (error "tfs/undo: No file")))
-
-
-
-;; -------------------------------------------------------
-;; tfs/history
-;; performs a TFS history: retrieve and display the TFS history of specified
file
-(defun tfs/history ()
- "perform a tf history on the specified file."
- (interactive)
- (if buffer-file-name
- (let* ((command (list tfs/tf-exe "history" "/format:detailed"
- buffer-file-name))
- (exitcode nil)
- (history-bufname (concat "*TFS-history* " buffer-file-name))
- (shortname (file-name-nondirectory buffer-file-name))
- (buffer (get-buffer-create history-bufname)))
- (save-excursion (set-buffer buffer) (erase-buffer))
- (tfs/append-to-message-buffer (concat "history " shortname ": "
- (prin1-to-string command)
"\n"))
- (setq exitcode (apply 'call-process
- (car command)
- nil
- history-bufname
- nil
- (append (cdr command) (list tfs/login))))
- (if (equal exitcode 0)
- (display-buffer history-bufname t)
- (error "tf history of %s was unsuccessful (%S)" shortname exitcode)))
- (error "tfs/history: No file")))
-
-
-;; -------------------------------------------------------
-;; tfs/properties
-;; gets information on the file being visited by the current buffer.
-;; displays that information in a new temp buffer.
-(defun tfs/properties ()
- "Performs a tf properties: gets TFS properties of the current file. "
- (interactive)
- (tfs/action "properties" nil))
-
-
-
-
-;; -------------------------------------------------------
-;; tfs/action
-;; gets information on the file being visited by the current buffer.
-;; diff, properties, etc
-;; displays that information in a new temp buffer.
-(defun tfs/action (verb retcode)
- "Performs a tf \"action\": gets a tf query for the current file. "
- (interactive)
- (if buffer-file-name
- (let* ((command (list tfs/tf-exe verb buffer-file-name))
- (exitcode nil)
- (info-bufname (concat "*TFS-" verb "* " buffer-file-name))
- (buffer (get-buffer-create info-bufname))
- (shortname (file-name-nondirectory buffer-file-name)))
- (save-excursion (set-buffer buffer) (erase-buffer))
- (tfs/append-to-message-buffer (concat verb shortname ": "
- (prin1-to-string command)
"\n"))
- (setq exitcode (apply 'call-process
- (car command)
- nil
- info-bufname
- nil
- (append (cdr command) (list tfs/login))))
-
- (if (or (equal exitcode 0) (not (numberp retcode)) (equal exitcode
retcode))
- (display-buffer info-bufname t)
- (error (concat "Get TFS " verb " for %s was unsuccessful (%S)")
- buffer-file-name exitcode)))
- (error "tfs/%s: No file" verb)))
-
-
-
-;; -------------------------------------------------------
-;; tfs/annotate
-(defun tfs/annotate ()
- "Gets line-by-line annotation for the file being visited by the current
buffer. Displays that information in the annotation viewer. This requires the
TFPT.exe tool. See 'tfs/tfpt-exe'."
- (interactive)
- (if (file-exists-p tfs/tfpt-exe)
- (if buffer-file-name
- (let* ((exitcode nil)
- (shortname (file-name-nondirectory buffer-file-name))
- (command (list tfs/tfpt-exe "annotate" "/noprompt"
- shortname))
- (annotation-bufname (concat "*TFS annotation* " shortname))
- (buffer (get-buffer-create annotation-bufname)))
- (save-excursion (set-buffer buffer) (erase-buffer))
- (message "computing...")
- ;;(message (apply 'concat command))
- (tfs/append-to-message-buffer (concat "annotate " shortname ": "
- (prin1-to-string command)
"\n"))
- (setq exitcode (apply 'call-process
- (car command)
- nil
- annotation-bufname
- nil
- (append (cdr command) (list tfs/login))))
-
- (if (equal exitcode 0)
- (progn
- (display-buffer annotation-bufname t)
- (beginning-of-buffer-other-window 0))
-
- (error "Get TFS properties for %s was unsuccessful (%S)"
- buffer-file-name exitcode)))
- (error "tfs/annotate: No file"))
- (error "%s does not exist. (have you set tfs/tfpt-exe?)" tfs/tfpt-exe)))
-
-
-;; -------------------------------------------------------
-;; tfs/thinginfo
-(defun tfs/thinginfo (exe thing)
- "Gets info on a workitem or changeset. This requires the TFPT.exe tool. See
'tfs/tfpt-exe'."
- (if (file-exists-p exe)
- (let* ((exitcode nil)
- (guess (thing-at-point 'word))
- (item-number (read-string (concat thing ": ") guess nil nil))
- (command (list exe thing item-number))
- (bufname (concat "*TFS " thing "* " item-number))
- (buffer (get-buffer-create bufname)))
- (save-excursion (set-buffer buffer) (erase-buffer))
- ;;(message (apply 'concat command))
- (tfs/append-to-message-buffer (concat thing " " item-number ": "
- (prin1-to-string command)
"\n"))
- (setq exitcode (apply 'call-process
- (car command)
- nil
- bufname
- nil
- (append (cdr command) (list tfs/login))))
-
- (if (equal exitcode 0)
- (progn
- (display-buffer bufname t)
- (beginning-of-buffer-other-window 0))
-
- (error (concat "Get TFS " thing "%s was unsuccessful (%S)"
- item-number exitcode))))
-
- (error "%s does not exist. (have you set tfs/tfpt-exe or tfs/tf-exe?)"
exe)))
-
-
-;; -------------------------------------------------------
-;; tfs/workitem
-(defun tfs/workitem ()
- "Gets info on a workitem. This requires the TFPT.exe tool. See
'tfs/tfpt-exe'."
- (interactive)
- (tfs/thinginfo tfs/tfpt-exe "workitem"))
-
-;; -------------------------------------------------------
-;; tfs/changeset
-(defun tfs/changeset ()
- "Gets info on a changeset. This requires the TFPT.exe tool. See
'tfs/tfpt-exe'."
- (interactive)
- (tfs/thinginfo tfs/tf-exe "changeset"))
-
-
-;; -------------------------------------------------------
-;; tfs/diff
-;; diff on the file being visited by the current buffer.
-(defun tfs/diff()
- "Performs a tf diff on the current file. "
- (interactive)
- (tfs/action "diff" 100))
-
-
-
-;; -------------------------------------------------------
-;; tfs/status
-;; tf status.
-(defun tfs/status ()
- "Performs a tf status. Displays the result in a buffer."
- (interactive)
- (let* ((command (list tfs/tf-exe "status"))
- (exitcode nil)
- (status-bufname "*TFS-status*")
- (buffer (get-buffer-create status-bufname)))
- (save-excursion (set-buffer buffer) (erase-buffer))
- (tfs/append-to-message-buffer (concat "status" ": "
- (prin1-to-string command)
"\n"))
- (setq exitcode (apply 'call-process
- (car command)
- nil
- status-bufname
- nil
- (append (cdr command) (list tfs/login))))
-
- (if (equal exitcode 0)
- (display-buffer status-bufname t)
- (error "Get TFS status was unsuccessful (%S)" exitcode))))
-
-
-(defun tfs/prep-message-buffer ()
- "scrolls the TFS Messages buffer to the end. Intended to be used by the
tfs.el module internally, before appending content to the messages buffer."
-
- (let ((buf (current-buffer))
- (tfsbuffer (get-buffer-create tfs/buffer-name)))
- (set-buffer tfsbuffer)
- (goto-char (point-max))
- (set-buffer buf)))
-
-
-(defun tfs/append-to-message-buffer (text)
- "Append text to the TFS Messages buffer. Intended for internal use only."
- (let ((buf (current-buffer))
- (tfsbuffer (get-buffer-create tfs/buffer-name)))
- (set-buffer tfsbuffer)
- (goto-char (point-max))
- (insert text)
- (set-buffer buf)))
-
-
-(provide 'tfs)
-
- [elpa] externals/csharp-mode a6f4b55 012/459: fix doc to remove mention of defunct flymake-for-csharp.el, (continued)
- [elpa] externals/csharp-mode a6f4b55 012/459: fix doc to remove mention of defunct flymake-for-csharp.el, ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode 6b688a6 014/459: update makefile, ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode fc60bff 019/459: Fix for breakage in Emacs 24.4, ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode 13984a8 004/459: First checkin of flymake-for-csharp.el, ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode 3414c63 006/459: First check in of Cscomp - C# code completion., ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode 756f086 003/459: Few updates to csharp-mode. First checkin of aspx-mode.el, for ASPX files., ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode 03ed8fb 016/459: v0.8.4 - fixes bug with yasnippet integration, ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode afe5315 022/459: Add GPL v2 license as found in the original project on Google Code., ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode e940015 023/459: Update readme-file., ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode d657aa0 025/459: Fix error in heading., ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode 2a28871 026/459: clean out unused files,
ELPA Syncer <=
- [elpa] externals/csharp-mode 77cbcf4 030/459: Add byte-compilation, unit-test running to makefile., ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode 35d295d 008/459: Fix a problem with parsing in csharp-completion.el, ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode 9f66d3b 011/459: fix doc to remove mention of flymake-command, ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode c47e9ea 017/459: v0.8.5 - updates to imenu, fontification, ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode 1119177 018/459: Small update in string-lastindexof, ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode 287f044 031/459: Automatically detect version during package-build based on elisp-content., ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode bd1d83e 044/459: Updated readme., ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode d33cfb6 046/459: Update readme with note about MELPA stable., ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode b286555 054/459: Ensure csharp-mode calls `prog-mode` hooks., ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode 78293bd 029/459: Add proper makefile for creating and publishing packages., ELPA Syncer, 2021/08/22