emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/csharp-mode 4fc9fad 010/459: Update C# completion stuff


From: ELPA Syncer
Subject: [elpa] externals/csharp-mode 4fc9fad 010/459: Update C# completion stuff
Date: Sun, 22 Aug 2021 13:58:44 -0400 (EDT)

branch: externals/csharp-mode
commit 4fc9fadc946829fbb9653df2403c8f35d68b3dac
Author: Dino Chiesa <dpchiesa@hotmail.com>
Commit: Dino Chiesa <dpchiesa@hotmail.com>

    Update C# completion stuff
---
 CscompUtilities.cs         | 1347 +++++++++++++++++++---
 CscompUtilities.dll        |  Bin 0 -> 57344 bytes
 ICSharpCode.NRefactory.dll |  Bin 0 -> 606208 bytes
 Readme.txt                 |   15 +-
 cscomp-base.el             |   35 +
 csharp-analysis.el         | 1533 +++++++++++++++++++++++++
 csharp-completion.el       | 2719 +++++++++++++++++++++++---------------------
 csharp-shell.el            |  294 +++--
 flymake-for-csharp.el      |  927 ---------------
 9 files changed, 4330 insertions(+), 2540 deletions(-)

diff --git a/CscompUtilities.cs b/CscompUtilities.cs
index 0b176f0..b24005e 100644
--- a/CscompUtilities.cs
+++ b/CscompUtilities.cs
@@ -1,5 +1,3 @@
-//#define CscompTrace
-
 // CscompUtilities.cs
 // ------------------------------------------------------------------
 //
@@ -7,21 +5,21 @@
 // built on host: DINOCH-2
 // Created Mon Apr 21 08:40:47 2008
 //
-// Last Saved: <2010-May-24 17:17:19>
+// Last Saved: <2011-May-12 15:19:19>
 //
 //
-// This thing defines 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.
+// 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 csde-complete, when the user asks for code-completion on a
-// segment of code, csde-complete will invoke a command in the
-// powershell - which really is just invoking a method on this static
+// 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 CSDE elisp logic.
+// 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
@@ -39,20 +37,24 @@
 //
 // ------------------------------------------------------------------
 //
-// Copyright (c) 2008-2010 by Dino Chiesa
+// 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")]
@@ -60,71 +62,171 @@ using System.Reflection;
 [assembly: AssemblyConfiguration("")]
 [assembly: AssemblyCompany("Dino Chiesa")]
 [assembly: AssemblyProduct("Tools")]
-[assembly: AssemblyCopyright("Copyright � Dino Chiesa 2010")]
+[assembly: AssemblyCopyright("Copyright � Dino Chiesa 2010, 2011")]
 [assembly: AssemblyTrademark("")]
 [assembly: AssemblyCulture("")]
-[assembly: AssemblyVersion("1.2.0.4")]
-
+[assembly: AssemblyVersion("1.3.0.2")]
 
 
 namespace Ionic.Cscomp
 {
     public static class Utilities
     {
-        private static readonly string DotNetDir= 
"c:\\windows\\Microsoft.NET\\Framework\\v2.0.50727";
-
-        private static string[] BaseAssembliesToLoad = {
-            // must be strong names
-            "System, Version=2.0.0.0, Culture=neutral, 
PublicKeyToken=b77a5c561934e089",
-            "mscorlib, Version=2.0.0.0, Culture=neutral, 
PublicKeyToken=b77a5c561934e089",
-        };
-
-
-        private static Dictionary<string,string> GacAssemblies =
-            new Dictionary<string,string>()
+        private static List<string> StarterAssemblies = new List<string>()
         {
-            {"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" },
+            "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",
-
+        //             "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()
         {
-            Tracing.SetupDebugConsole();
-            LoadAssembliesAndPopulateHashes();
+            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)
         {
@@ -153,31 +255,58 @@ namespace Ionic.Cscomp
 
         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";
+            }
 
-            // doesn't appear to be loaded. Try to load it.
-
+            // 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;
             }
 
-            _assembliesLoaded.Add(assemblyName, thisAssembly);
+            // 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)
@@ -212,9 +341,18 @@ namespace Ionic.Cscomp
                                 // sometimes we get duplicate types
                                 if (!list.Contains(t.FullName))
                                 {
-                                    _assemblyForType[t.FullName]= assemblyName;
                                     list.Add(t.FullName);
-                                    _fullNamesForShortNames[t.Name] = 
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)
@@ -231,7 +369,7 @@ namespace Ionic.Cscomp
                 }
             }
 
-            return assemblyName;
+            return shortName; // assemblyName
         }
 
 
@@ -243,8 +381,10 @@ namespace Ionic.Cscomp
             _fullNamesForShortNames = new Dictionary<String,String>();
             _assembliesLoaded       = new Dictionary<String,Assembly>();
 
-            for (int i=0; i<BaseAssembliesToLoad.Length; ++i)
-                InternalLoadOneAssembly(BaseAssembliesToLoad[i]);
+            foreach (var aname in StarterAssemblies)
+            {
+                InternalLoadOneAssembly(aname);
+            }
 
             Alphabetize();
         }
@@ -332,30 +472,40 @@ namespace Ionic.Cscomp
             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"))
+            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
                 {
-                    // try finding a DLL by that name in the .net2.0 directory.
-                    string GuessedDll = String.Format("{0}\\{1}", DotNetDir, 
assemblyName);
-                    if (System.IO.File.Exists(GuessedDll))
-                        a= Assembly.LoadFrom(GuessedDll) ;
+                    // look in search paths
+                    var fullname = FindAssemblyInSearchPaths(assemblyName);
+                    if (fullname != null && fullname != "nil")
+                    {
+                        a= Assembly.LoadFrom(fullname.Replace("\"", ""));
+                    }
                 }
             }
             else
             {
-                // try finding a DLL by that name in the .net2.0 directory.
-                string GuessedDll = String.Format("{0}\\{1}.dll", DotNetDir, 
assemblyName);
-                if (System.IO.File.Exists(GuessedDll))
-                    a= Assembly.LoadFrom(GuessedDll) ;
+                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;
+            return a; // maybe null
         }
 
 
@@ -370,17 +520,38 @@ namespace Ionic.Cscomp
         }
 
 
-
-
         public static String LoadOneAssembly (string name)
         {
             Tracing.Trace("LoadOneAssembly: {0}", name);
-            string r = InternalLoadOneAssembly(name);
-            Alphabetize();
+            try
+            {
+                string r = InternalLoadOneAssembly(name);
+
+                if (r == null)
+                {
+                    Tracing.Trace("LoadOneAssembly: null");
+                    return "nil";
+                }
 
-            if (r == null) return "nil";
-            if (r == "t") return r;
-            return "\"" + r + "\"";
+                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;
+            }
         }
 
 
@@ -433,11 +604,15 @@ namespace Ionic.Cscomp
         /// </returns>
         public static String GetCompletionsForNamespace(string ns)
         {
-            if (String.IsNullOrEmpty(ns)) return null;
+            if (String.IsNullOrEmpty(ns))
+            {
+                Tracing.Trace("GetCompletionsForNamespace: null input");
+                return null;
+            }
 
             if (!_typesForNamespace.ContainsKey(ns))
             {
-                //System.Console.WriteLine("t4n no contain '{0}'", ns);
+                Tracing.Trace("GetCompletionsForNamespace: unknown ns '{0}'", 
ns);
                 return null;
             }
 
@@ -446,8 +621,10 @@ namespace Ionic.Cscomp
             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));
-                result.Append("\"").Append(t.Substring(len)).Append("\" ");
+                //Tracing.Trace("    {0}", s);
+                result.Append("\"").Append(s).Append("\" ");
             }
             result.Append("))");
 
@@ -494,43 +671,49 @@ namespace Ionic.Cscomp
         /// </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 (!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)
             {
-                if (value.Equals(name))
-                    return String.Format("(list \"type\" \"{0}\")", value);
+                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)
             {
-                if (value.EndsWith(suffix))
-                    return String.Format("(list \"type\" \"{0}\")", value);
+                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...
@@ -541,7 +724,7 @@ namespace Ionic.Cscomp
                     return String.Format("(list \"namespace\" \"{0}\")", name);
             }
 
-            // match on the last segment of the namespace.  Eg, if name is 
"Diagnostics",
+            // Match on the last segment of the namespace.  Eg, if name is 
"Diagnostics",
             // should match on "System.Diagnostics".
             foreach (var key in collection)
             {
@@ -549,15 +732,18 @@ namespace Ionic.Cscomp
                     return String.Format("(list \"namespace\" \"{0}\")", key);
             }
 
-            // Finally, check the names of common namespaces that map to 
assemblies.
+            Tracing.Trace("checking GAC...");
+            // Finally, check the names of assemblies in the gac.
             // If found, load the assembly.
-            collection = GacAssemblies.Keys;
-            foreach (var key in collection)
+            collection = _GacAssemblies;
+            foreach (var strongname in collection)
             {
-                if (key.Equals(name))
+                var parts = strongname.Split(", ".ToCharArray());
+                if (parts!= null && parts[0].Equals(name))
                 {
-                    LoadOneAssembly(key + ", " + GacAssemblies[key]);
-                    return String.Format("(list \"namespace\" \"{0}\")", name);
+                    var r = LoadOneAssembly(strongname);
+                    if (r!=null && r != "nil")
+                        return String.Format("(list \"namespace\" \"{0}\")", 
name);
                 }
             }
 
@@ -589,6 +775,9 @@ namespace Ionic.Cscomp
         /// </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 + ".*$";
@@ -601,9 +790,12 @@ namespace Ionic.Cscomp
             {
                 foreach (var value in collection)
                 {
-                    Match match = Regex.Match(value,"^"+ns+reTypeStub);
-                    if (match.Success)
-                        responseSet.Add(String.Format("(list \"type\" 
\"{0}\")", value));
+                    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));
+                    }
                 }
             }
 
@@ -627,6 +819,22 @@ namespace Ionic.Cscomp
         }
 
 
+        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>
@@ -634,19 +842,24 @@ namespace Ionic.Cscomp
         ///   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)
+        public static String QualifyType(String typeName, String usinglist)
         {
-            var name = typeName;
             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();
@@ -657,58 +870,98 @@ namespace Ionic.Cscomp
             if (!name.Contains("."))
             {
                 Tracing.Trace("QualifyType: name contains no dot");
-                Tracing.Trace("QualifyType: examining {0} keys",
+                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}\")",
-                                          _fullNamesForShortNames[key],
-                                          
_assemblyForType[_fullNamesForShortNames[key]]);
+                                          tname,
+                                          _assemblyForType[tname]);
                     }
                 }
             }
 
-            // it may be a fully-qualified type name
+            // it may be a fully- or partially qualified type name
             Tracing.Trace("QualifyType: examining {0} full names",
                           _fullNamesForShortNames.Values.Count);
 
-            foreach (var value in _fullNamesForShortNames.Values)
+            foreach (var v1 in _fullNamesForShortNames.Values)
             {
-                if (stub == null || !value.StartsWith(stub))
+                foreach (var value in v1.Split(", ".ToCharArray()))
                 {
-                    int ix = value.LastIndexOf('.');
-                    stub= (ix > 0)
-                        ? value.Substring(0, ix)
-                        : value ;
-                    repeats = 0;
-                    if (residual!=null)
+                    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
                     {
-                        var r = residual.ToString();
-                        if (!String.IsNullOrEmpty(r))
-                            Tracing.Trace("  {0}", r);
+                        residual.Append(".");
+                        repeats++;
                     }
 
-                    residual = new System.Text.StringBuilder();
-                }
-                else
-                {
-                    residual.Append(".");
-                    repeats++;
-                }
-                if (repeats == 0)
-                    Tracing.Trace("  check: {0}.*", stub);
+                    // if (repeats == 0)
+                    //     Tracing.Trace("  check: {0}.*", stub);
 
-                // exact match
-                if (value.Equals(name))
-                {
-                    return
-                        String.Format("(list \"{0}\" \"{1}\")",
-                                      value,
-                                      _assemblyForType[value]);
+                    // check for exact match
+                    if (value.Equals(name))
+                    {
+                        return
+                            String.Format("(list \"{0}\" \"{1}\")",
+                                          value,
+                                          _assemblyForType[value]);
+                    }
                 }
             }
 
@@ -722,11 +975,18 @@ namespace Ionic.Cscomp
         {
             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();
@@ -736,7 +996,10 @@ namespace Ionic.Cscomp
 
         public static string GetTypeGivenVarDecl (string csharpVarDeclaration)
         {
-            return GetTypeGivenVarDecl(csharpVarDeclaration, null, null, -1,
+            return GetTypeGivenVarDecl(csharpVarDeclaration,
+                                       null,
+                                       null,
+                                       -1,
                                        "Foo1", // classname
                                        "", "");
         }
@@ -821,7 +1084,6 @@ namespace Ionic.Cscomp
                 Tracing.Trace("GetTypeGivenVarDecl: result {0}", res);
 
                 return res;
-
             }
             catch (System.Exception exc1)
             {
@@ -831,16 +1093,139 @@ namespace Ionic.Cscomp
         }
 
 
+        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 GetAssemblyPathForNamespace(String ns)
+        private static string GetShortAssemblyName(string ns)
         {
-            Assembly a = AssemblyIsLoaded(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)
-                return a.Location;
-            return 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 = "";
@@ -901,10 +1286,11 @@ namespace Ionic.Cscomp
                 "\nnamespace " + nsname + " {" +
                 "\n  class " + classname + " {" +
                 "\n    " + instanceMembers.Replace("; ",";\n    ")
-                                          .Replace("} ","}\n    ")
-                                          .Replace(";}","; }") +
+                .Replace("} ","}\n    ")
+                .Replace(";}","; }") +
                 "\n    void "+ methodname + " (" + arglist + ") {"+
-                "\n      " + fragment.Replace(";",";\n      ") +
+                "\n       " + fragment.Replace(";",";\n      ") +
+                "\n    " +
                 "}\n  }\n}\n";
 
             if (Verbose)
@@ -930,7 +1316,7 @@ namespace Ionic.Cscomp
                 {
                     Tracing.Trace("maybe add Ref: {0}", aName);
                     var path = GetAssemblyPathForNamespace(aName);
-                    if (path!=null)
+                    if (path!=null && path != "nil")
                         cp.ReferencedAssemblies.Add(path);
                 }
 
@@ -957,7 +1343,7 @@ namespace Ionic.Cscomp
                     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());
+                        Tracing.Trace(error.ToString());
                     return e.ToArray();
                 }
 
@@ -970,7 +1356,7 @@ namespace Ionic.Cscomp
             catch (System.Exception e1)
             {
                 var e = new List<String>();
-                e.Add("Exception during compile: " + e1.Message );
+                e.Add("Exception during compile: " + e1.ToString() );
                 Tracing.Trace("{0}", e1.ToString());
                 return e.ToArray();
             }
@@ -1026,8 +1412,6 @@ namespace Ionic.Cscomp
                 _Verbose = value;
             }
         }
-
-
     }
 
 
@@ -1214,10 +1598,18 @@ namespace Ionic.Cscomp
 
         internal String GetConstructorsSexp()
         {
-            if (mt==null) return "nil";
+            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) 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);
 
@@ -1528,23 +1920,25 @@ namespace Ionic.Cscomp
         }
     }
 
+
     internal static class Tracing
     {
-        #if UseCopyData
+#if UseCopyData
         private static  Ionic.CopyData.Transceiver transceiver;
-        #endif
+        private static bool _initialized;
+#endif
 
         [Conditional("CscompTrace")]
-        public static void SetupDebugConsole()
+        private static void SetupDebugConsole()
         {
-        #if UseCopyData
+#if UseCopyData
 
             // use object initializer syntax
             System.Diagnostics.Process p3 = new System.Diagnostics.Process
                 {
                     StartInfo =
                     {
-                        FileName = 
"c:\\dinoch\\vsp\\UnitTestProgressMonitor\\UnitTestProgressMonitor\\bin\\Debug\\UnitTestProgressMonitor.exe",
+                        FileName = 
"c:\\dev\\vsp\\UnitTestProgressMonitor\\UnitTestProgressMonitor\\bin\\Debug\\UnitTestProgressMonitor.exe",
                         Arguments = "-channel CscompShell",
                         CreateNoWindow = false,
                         UseShellExecute = false
@@ -1558,33 +1952,615 @@ namespace Ionic.Cscomp
             transceiver = new Ionic.CopyData.Transceiver();
             transceiver.Channel = "CscompShell";
 
-            transceiver.Send("title CSDE Shell Trace Monitor");
+            transceiver.Send("title *CscompShell* Trace Monitor");
 
             System.Threading.Thread.Sleep(400);
             transceiver.Send("log Hello from CscompShell");
-        #endif
+
+            _initialized = true;
+#endif
         }
 
 
         [Conditional("CscompTrace")]
         public static void Trace(string format, params object[] args)
         {
-        #if UseCopyData
+#if UseCopyData
+            if (!_initialized)
+            {
+                SetupDebugConsole();
+            }
+
             var s2 = String.Format(format, args);
             transceiver.Send("log " + s2);
-        #endif
+#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;
+            }
+        }
     }
 
+
 }
 
 
 
+
 /*
 
-  
[System.Reflection.Assembly]::LoadFrom("c:\\dinoch\\dev\\dotnet\\CscompUtilities.dll");
-  [Ionic.Cscomp.Utilities]::Verbose = $TRUE
+
 
   [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);} ')
 
@@ -1607,12 +2583,12 @@ namespace Ionic.Cscomp
 
 
 
-[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()
+  };');
 
-[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]::GetTypeGivenVarDecl(' var doo = "Tra la la"; var 
fred = new System.Collections.Generic.List<String> { doo.Length.ToString() };', 
$null, $null, 2);
 
 
 
@@ -1646,12 +2622,17 @@ namespace Ionic.Cscomp
   [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");
 
-  ;(debug-on-entry 'csde-complete-referenced-assemblies-list)
 
-  (semantic-brute-find-tag-by-class 'using)
 
 */
 
diff --git a/CscompUtilities.dll b/CscompUtilities.dll
new file mode 100644
index 0000000..de1a4ba
Binary files /dev/null and b/CscompUtilities.dll differ
diff --git a/ICSharpCode.NRefactory.dll b/ICSharpCode.NRefactory.dll
new file mode 100644
index 0000000..0c52ab5
Binary files /dev/null and b/ICSharpCode.NRefactory.dll differ
diff --git a/Readme.txt b/Readme.txt
index 0a19f30..0b9aa4e 100644
--- a/Readme.txt
+++ b/Readme.txt
@@ -1,9 +1,13 @@
 Created Mon, 24 May 2010  17:21
 Updated Fri, 13 May 2011  13:02
 
+x-URL: http://code.google.com/p/csharpmode/
+
 This is the readme for csharp-mode.
 
-You can use csharp-mode alone.  To do so,
+=======================================================
+
+You can use csharp-mode just as it is.  To do so,
 
  put this in your .emacs:
 
@@ -28,10 +32,13 @@ You can use csharp-mode alone.  To do so,
 
 =======================================================
 
-The c# code completion is undergoing  some changes.
-For now, don't use it.
+The c# code completion is experimental. It depends on
+ICSharpCode.NRefactory.dll,  as well as powershell.el and
+a few other .el modules.
+
+Use it and let me know how it goes for you.
+
 
 =======================================================
 
-x-URL: http://code.google.com/p/csharpmode/
 
diff --git a/cscomp-base.el b/cscomp-base.el
new file mode 100644
index 0000000..420ff27
--- /dev/null
+++ b/cscomp-base.el
@@ -0,0 +1,35 @@
+;;; 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
new file mode 100644
index 0000000..ffa829f
--- /dev/null
+++ b/csharp-analysis.el
@@ -0,0 +1,1533 @@
+;;; 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
index d7f0def..69e837d 100644
--- a/csharp-completion.el
+++ b/csharp-completion.el
@@ -3,66 +3,220 @@
 ;; Author:     Dino Chiesa <dpchiesa@hotmail.com>
 ;; Maintainer: Dino Chiesa <dpchiesa@hotmail.com>
 ;; Created:    April 2010
-;; Modified:   April 2010
-;; Version:    0.1.5
+;; Modified:   January 2011
+;; Version:    0.2
 ;; Keywords:   c# languages oop mode
 ;; X-URL:      http://code.google.com/p/csharpmode/
 ;;
 ;;
 ;;; Commentary:
 ;;
-;;    This is a code-completion or "intellisense" package for C#.  The
-;;    scope of this module is much smaller that a full "development
-;;    envvironment".  It does smart code completion for C#, in
-;;    emacs. It does not do font-lock, indenting, debugging,
-;;    compiling, profiling, and so on.
-;;
-;;    To use it, place the cursor after a partially-completed
-;;    statement, and invoke `cscomp-complete-at-point'.  Normally this
-;;    would be bound to a particular keystroke, like M-.  This module
-;;    will insert the first completion that matches. If multiple
-;;    completions are possible, calling the completion function again
-;;    will cycle through the possibilities, similar to the way
-;;    dabbrev-mode works.
-;;
-;;    You can also call `cscomp-complete-at-point-menu', and get a popup
-;;    menu of the completion choices.
-;;
-;;    There are 2 complementary sources of information for the
-;;    completions: introspection into compiled .NET class libraries
-;;    (like the base class library), and parse analysis from the
-;;    semantic.el package, which is part of CEDET. In the typical
-;;    case, this module uses both of those sources of information,
-;;    together.
-;;
-;;    The reflection is done by an inferior powershell shell running
-;;    within emacs, that has loaded a custom .NET assembly.  The
-;;    library exposes static methods that perform type reflection,
-;;    using the capabilities of the System.Reflection namespace. These
-;;    methods then return strings which are lisp s-expressions that
-;;    can be eval'd, resulting in structures containing information
-;;    for a given type - including the available methods, fields and
-;;    properties, and the attributes on same.  This piece of the
-;;    puzzle is called the "CscompShell".
-;;
-;;    As an example, suppose your code has a local variable of type
-;;    System.Xml.XmlDocument, named doc.  Suppose the user asks for
-;;    completion on that variable.  The module uses the semantic parse
-;;    data 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 an s-expression
-;;    enumerating the fields, methods and properties for that type.
-;;    This s-expression is then used to populate the completion list.
-;;
-;;
-;; Here's a survey of the situations in which this module can offer
-;; completions:
+;;    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 type-ahead completion, font-lock,
+;;    indenting, debugging, compiling, profiling, or management of C#
+;;    project files. For other C# things, see these other modules:
+;;
+;;      csharp-mode.el - font-lock and indenting for C#.
+;;
+;;      flymake-for-csharp.el - enhancement of flymake for C#.
+;;
+;; 
-----------------------------------------------------------------------------
+;;
+;;    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.
 ;;
-;;         void Method1(String longArgumentName)
+;;         int lengthOfList;
+;;         void Method1(String lengthyArgumentName)
 ;;         {
-;;            long?
+;;            leng?
 ;;         }
 ;;
 ;;    b. Methods, fields and properties (m/f/p) on a local variable
@@ -77,35 +231,36 @@
 ;;         var x = "this is a string";
 ;;         x.?
 ;;
-;;    d. Cascading local variable declarations of var type:
+;;    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. completion on generic types:
-;;
-;;         var x = new List<String>();
-;;         x.?
-;;
-;;    f. completion on local variables that are initialized
+;;    e. M/f/p on local variables that are initialized
 ;;       from instance methods and variables.
 ;;
 ;;         void method1()
 ;;         {
-;;           var length = this.InstanceMethod();
-;;           length.?
+;;             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 constructors among qualified and unqualified types
+;;    i. finding types and namespaces:
 ;;
 ;;         var x = new TimeS?
 ;;
@@ -127,80 +282,64 @@
 ;;
 ;;         Path.GetRandomFileName().Normalize().?
 ;;
+;; 
-----------------------------------------------------------------------------
 ;;
+;; things that need to be tested or fixed:
 ;;
-;; =======================================================
-;;
-;; Dependencies:
-;;
-;;   cc-mode 5.31.?
-;;
-;;   semantic.el 1.0pre7
-;;
-;;   optionally, yasnippet, for snippet insertion.  If the user 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.
+;;      return new XmlS?
 ;;
-;;   PowerShell, and a separate DLL that must run in Powershell.  That
-;;     DLL is implemented in C#.
+;;      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 :
 ;;
-;;    1. The module does not do completion on anonymous (var) types in
-;;       for loops.
-;;
-;;
 ;;
 ;; TODO :
 ;;
 ;;    make an installer.
 ;;
-;; Please send any comments, bugs, or upgrade requests to
-;; Dino Chiesa (dpchiesa@hotmail.com)
+;; Please send any comments, bugs, enhancements, or suggestions or
+;; requests for upgrades to Dino Chiesa (dpchiesa@hotmail.com)
 ;;
 
-
-(require 'csharp-shell)
-
-(require 'semantic-idle)  ;; for ... reparsing a buffer
-
-
-;; Design notes:
-;;
-;; Tue, 04 May 2010  10:47
-;;
-;; This completion depends on the semantic package for parsing a C#
-;; buffer.  That gives the module a way to interrogate the names and
-;; types of local and instance variables, in order to do completion on
-;; them.
-;;
-;; Semantic also provides the list of using statements for a C# module,
-;; which tells us which assemblies we need to search in, for
-;; completions.  These are then loaded into CscompShell for interrogation.
-;;
+(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 completion. Each element of the list is
-either a string, or a list which the car is the possible completion,
-and the cadr is an additional information about this completion.")
+  "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.")
+  "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.")
@@ -215,414 +354,180 @@ cycle the list.")
   :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-list ()
-  "Return the list of .NET namespaces referenced in the
-current buffer via using statements. It uses the semantic parser
-table to find the 'using' statements. "
-  (interactive)
-  (if (not (semantic-active-p)) (semantic-new-buffer-fcn))
-  (let* ((tokens  (semantic-fetch-tags))
-         ;;(usings (semantic-find-nonterminal-by-token (quote include) tokens))
-         (usings (semantic-brute-find-tag-by-class 'include tokens)))
-    (cscomp-log 3 "cscomp-referenced-assemblies-list: found using statements: 
'%s'" usings)
-    (mapcar 'car usings)))
-
-
-
-(defun cscomp-instance-vars ()
-  "Return the list of instance variables in a C# module.
-This uses the semantic parser table to find the variable
-declarations.
 
-The return value is a list of semantic tags.  Looks like:
+(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:
 
-\((\"flavor\" variable
-             (:type \"int\")
-             (reparse-symbol class_member_declaration) #<overlay from 580 to 
595 in a.cs>)
- (\"flicky\" variable
-             (:type \"String\")
-             (reparse-symbol class_member_declaration) #<overlay from 604 to 
636 in a.cs>)
- (\"label\" variable
-            (:type \"String\")
-            (reparse-symbol class_member_declaration) #<overlay from 645 to 
669 in a.cs>))
+ (\"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))
 
-  (if (not (semantic-active-p)) (semantic-new-buffer-fcn))
-  (semantic-fetch-tags)
-  (let* ((class  (cscomp-find-enclosing-csharp-class))        ;; the enclosing 
class
-         (tokens (semantic-tag-type-members class))                  ;; the 
members of that class
-         (vars (semantic-brute-find-tag-by-class 'variable tokens))) ;; the 
members that are variables
-    (cscomp-log 3 "cscomp-instance-vars: found instance vars: '%s'" vars)
-    vars))
-
-
-
-
-(defun cscomp-instance-members ()
-  "Return the list of instance members in a C# module.
-This uses the semantic parser table to find the memebr
-declarations.
-
-The return value is a list of semantic tags.  Looks like:
-
-\((\"flavor\" variable
-             (:type \"int\")
-             (reparse-symbol class_member_declaration) #<overlay from 580 to 
595 in a.cs>)
- (\"Hello\" function
-             (:type \"String\")
-             (reparse-symbol class_member_declaration) #<overlay from 604 to 
636 in a.cs>)
- (\"label\" variable
-            (:type \"String\")
-            (reparse-symbol class_member_declaration) #<overlay from 645 to 
669 in a.cs>))
-
-"
 
-  (if (not (semantic-active-p)) (semantic-new-buffer-fcn))
-  (semantic-fetch-tags)
-  (let ((class  (cscomp-find-enclosing-csharp-class))) ;; the enclosing class
-    (semantic-tag-type-members class)))                       ;; the members 
of that class
 
+(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 tagset &optional local)
+(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',
+`cscomp-matching-instance-vars', and
 `cscomp-matching-instance-members'.
+
 "
-    (let ((var-label (if local "(Variable) " "(Field) " ))
-           result)
+  (let ((var-label (if local "(Variable) " "(Field/Prop) " ))
+        result)
 
-    (if tagset
+    (if nodeset
         (progn
-        (while tagset
-          (let* ((tag (car tagset))
-                 (member-name  (semantic-tag-name tag))
-                 (member-type  (semantic-tag-type tag))
-                 (member-clazz (semantic-tag-class tag))
-                 )
-
-            (if (eq 0 (string-match name-fragment member-name))
-                (let ((descrip
-                       (cond
-                        ((string= member-clazz "variable")
-                         (concat var-label member-type))
-
-                        ((string= member-clazz "function")
-                         (let* ((arglist (semantic-tag-get-attribute tag 
:arguments))
-                                (modifiers (semantic-tag-modifiers tag))
-                                (arg-descrip
-                                 (if (> (length arglist) 0)
-                                     (concat "("
-                                             (mapconcat
-                                              '(lambda (x) (concat 
(semantic-tag-type x)
-                                                                   " "
-                                                                   
(semantic-tag-name x)))
-                                              arglist  ", ")
-                                             ")")
-                                   "()")))
-
-                           (concat "(Method) "
-                                   " " (mapconcat 'identity modifiers " ") " "
-                                   arg-descrip
-                                   "  returns "
-                                   member-type)))
-
-                        (t ""))))
-
-
-                  (cscomp-log 2 "cscomp-matching-tags: found %s (%s)"
-                           member-name member-type)
-
-                  (setq result (cons (list member-name descrip) result)))))
-
-            (setq tagset (cdr tagset)))
-        (cscomp-sort-completion-list result))
+          (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 a C# module, that
+  "Return the list of instance variables in scope, that
 match NAME-FRAGMENT.  See also, `cscomp-matching-local-vars'.
 
 "
-  (cscomp--find-matching-tags name-fragment (cscomp-instance-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 a C# module, that
+  "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'.
 
 "
-  (cscomp--find-matching-tags name-fragment (cscomp-instance-members)))
+  (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)
-  "Use the semantic lex/analysis results to find local variables
-that match the given 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'.
 
 "
-  (cscomp-start-stripped-semantic)
-  (cscomp--find-matching-tags name-fragment (semantic-get-all-local-variables) 
t))
-
-
-
-(defun cscomp-find-enclosing-csharp-class (&optional posn)
-  "returns a tag of type 'type (in other words, a c# class or struct) that
-encloses POSN, or point if POSN is nil.  If there is no enclosing 'type,
-then return nil.
-"
-;; This isn't quite correct. At this time, the C# namespace defn gets
-;; parsed as a type. I couldn't figure how to get namespace to get
-;; parsed as a new 'namespace tag.  Therefore, this fn can sometimes
-;; return a tag corresponding to a namespace, as opposed to a tag
-;; corresponding to a bonafide type.
-
-(let ((nar (semantic-current-tag-of-class 'type)))
-    nar))
-
-
-
-;; (defun cscomp-find-semantic-things (tag-class)
-;;   "Search for tags in semantic parse state."
-;;   (interactive "sTag type: ")
-;;   (if (not (semantic-active-p)) (semantic-new-buffer-fcn))
-;;   (let* ((tokens  (semantic-fetch-tags))
-;;          (matches (cscomp-find-by-class tag-class tokens t)))
-;;     (if matches
-;;         (while matches
-;;           (let ((one (car matches)))
-;;             (setq matches (cdr matches))))
-;;       nil
-;;     )))
-
-
-
-(defun cscomp-find-by-class (cls streamorbuffer &optional search-parts 
search-includes)
-  "Find all tags with class CLS within STREAMORBUFFER.
-CLS is a string which is the name of the class of the tags returned, such as
-include, variable, type.
-See `semantic-tag-class'.
-Optional argument SEARCH-PARTS and SEARCH-INCLUDES are passed to
-`semantic-brute-find-tag-by-function'."
-  (semantic-brute-find-tag-by-function
-   (lambda (tag)
-     (let ((class (semantic-tag-class tag)))
-       (string= class cls)))
-   streamorbuffer search-parts search-includes))
-
-
-
-;;    (lambda (tag)
-;;      (let ((class (semantic-tag-class tag)))
-;;        (if (and (listp ts)
-;;                 (or (= (length ts) 1)
-;;                     (string= (semantic-tag-class ts) type)))
-;;
-;;            (setq ts (semantic-tag-name ts)))
-;;        (equal type ts)))
-;;    streamorbuffer search-parts search-includes))
-
-
-
-(defun cscomp-debugonly-list-all-local-variables ()
-  "fiddle with local variables and semantic."
-  (interactive)
-  (cscomp-start-stripped-semantic)
-  (semantic-lex (point-min) (point-max) 100)
-  (let ((locals (semantic-get-all-local-variables)))
-    (mapcar '(lambda (x)
-               (cscomp-log 3 "local var: name(%s) type(%s) pos(%s)"
-                        (car x) (cadr (nth 2 x))
-                        (nth 4 x)))
-            locals)))
-
-
-
-;; (defun cscomp-variables-in-scope ()
-;;   "Return the list of variables currently in scope.
-;; It uses the semantic parser table to find them."
-;;   (interactive)
-;;   (if (not (semantic-active-p)) (semantic-new-buffer-fcn))
-;;   (let* ((tokens (semantic-fetch-tags))
-;;          (vars (semantic-brute-find-tag-by-class 'variable tokens)))
-;;     (cscomp-log 3 "cscomp-variables-in-scope: found variables: '%s'" vars)
-;;     (mapcar 'car vars)))
-
-
-;; (defun cscomp-valid-csharp-declaration-at (point varname)
-;;   "Verify that a POINT starts a valid csharp declaration
-;; for the VARNAME variable."
-;;   (save-excursion
-;;     (goto-char point)
-;;     (if (looking-at
-;;          (concat "\\([A-Za-z0-9_.\177-\377]+\\)[ \t\n\r]+"
-;;                  (cscomp-double-backquotes varname)
-;;                  "[ \t\n\r]*[;=]"))
-;;         (match-string 1)
-;;       nil)))
-
-
-
-
-;; (defun cscomp-double-backslashes (varname)
-;;   "Build a new string identical to VARNAME, except that every backslash
-;; `\' is doubled, so that it can be used in a regex expression.
-;; "
-;;   (let (result (idx 0) (len (length varname)) curcar)
-;;     (while (< idx len)
-;;       (setq curcar (elt varname idx))
-;;       (setq result (concat result (if (eq curcar ?\\)
-;;                                       "\\\\"
-;;                                     (make-string 1 curcar))))
-;;       (setq idx (1+ idx)))
-;;     result))
-
-
-
-
-;; (defun cscomp-declared-type-of (name)
-;;   "Find in the current buffer the csharp type of the variable NAME.  The
-;; function returns a string containing the name of the class, or nil
-;; otherwise. This function does not give the fully-qualified csharp class
-;; name, it just returns the type as it is declared."
-;;   (save-excursion
-;;     (let (found res pos orgpt resname)
-;;       (while (and (not found)
-;;                   (search-backward name nil t))
-;;         (setq pos (point))
-;;         (backward-word 1)
-;;         (setq resname (cscomp-valid-csharp-declaration-at (point) name))
-;;         (goto-char pos)
-;;         (forward-char -1)
-;;         (if resname
-;;             (progn (setq res resname)
-;;                    (setq found t))))
-;;       res)))
-
-
-;; (defun cscomp-filter-fqn (importlist)
-;;   "Filter all the fully-qualified classnames in the import list. It uses
-;; the knowledge that those classnames are at the beginning of the list,
-;; so that it can stops at the first package import (with a star `*' at
-;; the end of the declaration)."
-;;   (if importlist
-;;       (if (string= "*" (car (cdr (car importlist))))
-;;           importlist
-;;         (cscomp-filter-fqn (cdr importlist)))))
-
-
-
-(defun cscomp-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.
-
-"
-  (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 cscomp-send-string-to-shell (command-string)
-  "sends a string to cscompshell function, returns the result."
-  (let ((result (csharp-shell-exec-and-eval-result command-string)))
-    (cscomp-log 2 "send-string-to-shell (%s) result(%s)" command-string 
(prin1-to-string  result))
-    ;;(if (and result (listp result)) result nil)
-    result
-    ))
-
-
-
-(defun cscomp-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 (cscomp-escape-string-for-powershell arg)))
-    (cscomp-send-string-to-shell (concat "[Ionic.Cscomp.Utilities]::" fn "(\'" 
escaped-arg "\')"))))
-
-
+  (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 given type is known by the CscompShell.  You can provide 
a short type name, or a fully-qualified name.  You must have loaded the 
assembly into the shell, for it to be known.  See `cscomp-load-assembly'."
-  (interactive "sType name: ")
-  (cscomp-invoke-shell-fn "QualifyType" typename))
-
-
-
-(defun cscomp-get-members-of-class (semantic-tag)
-  "Gets the members of the class denoted by the SEMANTIC-TAG.
-If SEMANTIC-TAG is nil, then this function gets the closest type
-containing point, and gets the members of that.
-
+  "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'.
 "
-  (if (null semantic-tag) (setq semantic-tag (cscomp-get-current-class)))
-  (if (eq (cadr semantic-tag) 'type)
-      (semantic-tag-type-members semantic-tag)
-    nil))
-
-
-
+  (interactive "sType name: ")
+  (csharp-shell-invoke-shell-fn "QualifyType" typename))
 
-(defun cscomp-get-current-class (&optional posn)
-  "Return the semantic tag for the current class or type in scope at POSN.
-"
-  (interactive)
-  (save-excursion
-    (if posn (goto-char posn))
-    (semantic-fetch-tags)
-    (let ((containing-type (semantic-current-tag-of-class 'type)))
-      containing-type)))
 
 
-(defun cscomp-produce-csharp-arglist-block-from-dbrecord (arglist)
-  "Produces an argument list block, suitable for framing within parens
-in a method declaration, from ARGLIST, a list of local arguments obtained from
-`semantic-get-local-arguments'.
+(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:
 
-   ((\"count\"
-      variable
-      (:type \"int\")
-      (:filename \"c:/dinoch/dev/dotnet/CsharpCompletion.cs\"
-                 reparse-symbol formal_parameters)
-      [621 630])
-    (\"melvin\"
-      variable
-      (:type \"string\")
-      (:filename \"c:/dinoch/dev/dotnet/CsharpCompletion.cs\"
-                 reparse-symbol formal_parameters)
-      [631 645]))
+  ((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:
 
@@ -630,13 +535,12 @@ The return value is like this:
 
 When the arglist is empty, the return value is a string of zero length.
 
-
 "
   (let ((fragment ""))
     (while arglist
       (let* ((x (car arglist))
-             (var-name (car x))
-             (var-type (cadr (nth 2 x))))
+             (var-name (cadr x))
+             (var-type (caddr x)))
 
         (setq fragment (concat fragment var-type " " var-name)
               arglist (cdr arglist))
@@ -648,10 +552,16 @@ When the arglist is empty, the return value is a string 
of zero length.
 
 
 (defun cscomp-produce-instance-member-code-fragment (member-list)
-  "Produce a C# fragment that defines placeholder instance members,
-to be inserted into a class template which 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.
+
+"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
@@ -664,28 +574,27 @@ generates C# code to provide those instance members.
 
 For input that looks like this:
 
-  ((\"staticField1\" variable
-     (:typemodifiers (\"private\" \"static\") :type \"int\")
-     (reparse-symbol class_member_declaration)
-     #<overlay from 605 to 642 in CsharpCompletion.cs>)
-   (\"InstanceMethod1\" function
-     (:arguments (...) :type \"string\")
-     (reparse-symbol class_member_declaration)
-     #<overlay from 652 to 741 in CsharpCompletion.cs>)
-   (\"Run\" function
-     (:typemodifiers (\"public\") :arguments (...) :type \"void\")
-     (reparse-symbol class_member_declaration)
-     #<overlay from 752 to 1487 in CsharpCompletion.cs>)
-   (\"Main\" function
-     (:typemodifiers (\"public\" \"static\") :arguments (...) :type \"void\")
-     (reparse-symbol class_member_declaration)
-     #<overlay from 1497 to 1806 in CsharpCompletion.cs>)
+  ((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:
 
-    private static int staticField1 = default(int);
-    string InstanceMethid(...) { return default(string); }
+    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.
@@ -695,56 +604,43 @@ types of local variables declared in methods.
 
     (while member-list
       (let* ((x (car member-list))
-             (member-name (car x))
-             (member-flavor (cadr x))
-             (member-type (semantic-tag-get-attribute x :type))
-             (member-modifiers (semantic-tag-get-attribute x :typemodifiers))
-             one-frag
-             )
-        ;;          (message "n(%s) f(%s) t(%s)"
-        ;;                   member-name
-        ;;                   member-flavor
-        ;;                   member-type)
+             (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
 
-               ((string= member-type "void") ;; the member is a void type
+               ((or
+                (string= member-type "void") ;; the member is a void type
+                (string= member-type "System.Void"))
                 "")                          ;; emit nothing, don't need it.
-               ;; it's possible we might need it, in which case,
+
+               ;; if it turns out I was wrong, and the fn is necessary,
                ;; we can just emit an empty fn.
 
-               ((eq member-flavor 'function) ;; it's a method
-                (concat
-                 (mapconcat 'identity member-modifiers " ")
-                 " "
-                 member-type
-                 " "
-                 member-name
-                 "("
-                 (cscomp-produce-csharp-arglist-block-from-dbrecord
-                  (semantic-tag-get-attribute x :arguments))
-                 ") {"
-                 (if member-type
-                     (concat
-                      " return default("
-                      member-type
-                      ");")
-                   "")
-                 "} "))
-
-
-               ((eq member-flavor 'variable) ;; it's an instance variable
+               ((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
-                 (mapconcat 'identity member-modifiers " ")
-                 " "
-                 member-type
-                 " "
-                 member-name
-                 " = default("
-                 member-type
-                 "); "))
+                 member-modifiers " " member-type " "
+                 member-name " = default(" member-type "); "))
 
                (t
                 "")))
@@ -776,26 +672,25 @@ to a single space.
   "Escape single-quotes in the given string S.  This is for use within
 powershell.
 "
-  ;; escape single-quotes
-  (while (string-match "\\(.+\\)'\\(.+\\)" s)
-    (setq s
-          (concat
-           (substring s 0 (match-beginning 1))
-           "`'"
-           (substring s (match-end 1)))))
+  (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)
 
 
-;;(setq cscomp-log-level 2)
-
-
-(defun cscomp-get-var-type-given-decl (var-declaration
-                                              var-index
-                                              classname
-                                              arglist
-                                              instance-members)
+(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
+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,
@@ -816,10 +711,16 @@ 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-list) 
","))
+         (namespaces (mapconcat 'identity (cscomp-referenced-assemblies) ","))
          (command-string
           (concat "[Ionic.Cscomp.Utilities]::GetTypeGivenVarDecl('"
                   massaged-decl
@@ -835,7 +736,7 @@ the initializer for the var, if any.
                   "','"
                   (cscomp-consolidate-whitespace instance-members)
                   "')" )))
-    (cscomp-send-string-to-shell command-string)))
+    (csharp-shell-do-shell-fn command-string)))
 
 
 
@@ -844,9 +745,27 @@ the initializer for the var, if any.
   "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-assembly'."
+See `cscomp-load-one-assembly'."
   (interactive "sNamespace: ")
-  (cscomp-invoke-shell-fn "GetCompletionsForNamespace" ns))
+  (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))))
 
 
 
@@ -868,41 +787,57 @@ Result is
 "
 
   (interactive "sname to qualify: ")
-  (cscomp-invoke-shell-fn "QualifyName" name))
+  (csharp-shell-invoke-shell-fn "QualifyName" name))
 
 
-(defun cscomp-get-matches (fragment)
+(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:
 
-   (list (list \"type\"  \"fullNameOfType\")
-         (list \"namespace\"  \"FullNameOfNamespace\"))
+   ((\"type\"  \"fullNameOfType\")
+    (\"namespace\"  \"FullNameOfNamespace\")
+    (\"method\"  \"NameOfMethod\")
+    (\"variable\"    \"woof\" \"(local) System.Int32\"))
 
 "
   (interactive "sfragment to match on: ")
 
-  (let ((namespaces (mapconcat 'identity (cscomp-referenced-assemblies-list) 
",")))
-
-    (cscomp-send-string-to-shell
-     (concat "[Ionic.Cscomp.Utilities]::GetMatches('"
-             fragment
-             "','"
-             namespaces
-             "')"))))
-
+  (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-additional-assemblies (lib-list)
-"Loads a set of assemblies into the csharp-shell, which then allows Cscomp
-to do completion (etc) on the types in those libraries."
-  (mapcar 'cscomp-load-assembly lib-list))
 
 
-(defun cscomp-load-assembly (lib)
-  "Loads a assembly into the csharp-shell, which then allows Cscomp
-to do completion (etc) on the types in that library."
-  (interactive "sLibrary: ")
-  (cscomp-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)))
 
 
 
@@ -911,57 +846,36 @@ to do completion (etc) on the types in that library."
 list of referenced assemblies. It returns a string if the fqn
 was found, or null otherwise."
   (interactive "sType name: ")
-  (cscomp-log 1 "get-qualified-name (%s)" name)
+  (cscomp-log 2 "get-qualified-name (%s)" name)
   (let ((result (cscomp-type-exists name)))
     (if result result
       ;; else
-      (let ((usinglist (cscomp-referenced-assemblies-list))
+      (let ((usinglist (cscomp-referenced-assemblies))
             fullname namespace )
 
         ;; usinglist is like this:
-        ;; ("System"  "System.Collections"  "System.Collections.Generic"  
"System.Reflection")
+        ;; ("System"  "System.Collections"  "System.Collections.Generic" ...)
 
         (setq result nil)
         (while usinglist
           (setq namespace (car usinglist))
-          (cscomp-load-assembly namespace)
+          (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)
-            (setq usinglist (cdr usinglist))))
-
-        (cscomp-log 1 "get-qualified-name rtns: '%s'" result)
+                    usinglist nil)  ;; end the loop
+            (setq usinglist (cdr usinglist)))))
 
-        result))))
+        (cscomp-log 2 "get-qualified-name (%s): '%s'" name result)
 
+        result)))
 
 
-;; (defun cscomp-flush-typeinfo-cache ()
-;;   "Flushes all entries in the completion cache"
-;;   (interactive)
-;;   (setq cscomp-typeinfo-cache nil))
-;;
-;;
-;; (defun cscomp-flush-classes-in-cache (class-list)
-;;   "Flushes all the classes in CLASS-LIST as entries of cache."
-;;   (let ((temp (nth 0 cscomp-typeinfo-cache))
-;;         (index -1)
-;;         (found nil)
-;;         (class (car class-list)))
-;;     (while class
-;;       (while (and temp (not found))
-;;         (setq index (1+ index))
-;;         (setq temp (nth index cscomp-typeinfo-cache))
-;;         (if (string= (car temp) class)
-;;             (setq found t)))
-;;       (if found
-;;           (setq cscomp-typeinfo-cache
-;;                 (nthcdr (1+ index) cscomp-typeinfo-cache)))
-;;       (setq class-list (cdr class-list))
-;;       (setq class (car class-list))
-;;       (setq found nil))))
+(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)
@@ -972,29 +886,36 @@ was found, or null otherwise."
           (setq new-list (list new-entry nil))
           (setcdr new-list (cdr cscomp-typeinfo-cache))
           (setq cscomp-typeinfo-cache new-list)
-          (cscomp-log 1 "cache is full")   )
+          (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)
-  (let ((temp (nth 0 cscomp-typeinfo-cache)) (index -1) (found nil))
-    (while (and temp (not found))
-      (setq index (1+ index))
-      (cscomp-log 2 "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 "cscomp-get-typeinfo-from-cache: HIT name(%s) r(%s)"
-                    name (prin1-to-string (nth 1 temp)))
-          (nth 1 temp))
-      (cscomp-log 1 "cscomp-get-typeinfo-from-cache: MISS name(%s)" name)
-      nil)))
+(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)
@@ -1007,49 +928,59 @@ informations on the completion - the property type, or 
the param
 list and return type for a method, etc."
   (interactive "sTypename: ")
 
-  (cscomp-log 2 "cscomp-get-typeinfo name(%s)...trying cache..." name)
-
-  (let ((type-info (cscomp-get-typeinfo-from-cache name))
-        (usinglist (cscomp-referenced-assemblies-list))
-        namespace
-        qualified-type )
-
-    ;; load all the assemblies mentioned in the using clauses
-    (while usinglist
-      (setq namespace (car usinglist))
-      (cscomp-load-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
-                                    "')")))
-
-          (cscomp-log 1 "cscomp-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))
+  (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: ")
-  (cscomp-invoke-shell-fn "GetConstructors" type-name))
+  (csharp-shell-invoke-shell-fn "GetConstructors" type-name))
 
 
 
@@ -1064,10 +995,10 @@ When the string does not contain a dot, this fn returns a
 element is the entire string.
 
 "
-  (cscomp-log 2 "cscomp-split-by-dots: s[%s]" s)
+  (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 "cscomp-split-by-dots: %s" (prin1-to-string result))
+        (cscomp-log 2 "split-by-dots: %s" (prin1-to-string result))
         result)
     (list nil s))) ;; it's a single atom
 
@@ -1076,40 +1007,63 @@ element is the entire string.
 
 (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.
 
-The retval 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.
 
-For example, suppose System.Diagnostics.D were the name at
+#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.
 
-It's just an exercise in syntactically-aware string parsing.
+
+#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.
+returns nil, and does not set the markers.
 
 "
+  (interactive)
+
   (cscomp-log 2 "parse-csharp-expression-before-point: point(%d)" (point))
 
-  (interactive)
   (save-excursion
     (let ((opoint (point))
           (cycle-count 0)
           (dot-count 0)
-          m1
-          (regex "[-\\+\\*\\/%,;( {})=\\.]")
-          snip done
+          (regex "[-\\+\\*\\/%,;|( {})=\\.]")
+          snip done m1
           (paren-depth 0)
-          ;;           (skip-back '(lambda ()
-          ;;                         (skip-chars-backward "\t ")
-          ;;                         (backward-char)))
-          )
+          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)
 
@@ -1157,15 +1111,17 @@ returns nil.
             ;;(funcall skip-back))
             t)
 
-
            ((or
              (eq (char-after) 32)   ;; space
              (eq (char-after) ?\t)) ;; tab
-            t)                      ;; do nothing
+            (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)
-                  regex "[-\\+\\*\\/%,;( {})=]"))
+            (setq m1 (point))
+            (setq regex "[-\\+\\*\\/%,;|( {})=]"))
 
            (t
             (setq done t))))
@@ -1175,290 +1131,341 @@ returns nil.
 
         (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-expression-before-point: B snip(%s)" snip)
-      (list (1+ (point)) (cscomp-split-by-dots snip)))
-    ))
+      (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-qualify-local-var (symbol opoint)
-  "Use the semantic lex/analysis results to classify the
-name as a local 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-instance-var'.
-"
-  (cscomp-start-stripped-semantic)
-  ;;(semantic-lex (point-min) (point-max) 100)
-  (let ((locals (semantic-get-local-variables))
-        (args (semantic-get-local-arguments))
-        (result nil)
-        (decl-count 0)
-        (prior-var-decls ""))
-
-    (while (and locals (not result))
-      (let* ((x (car locals))
-             (var-name (car x))
-             (var-type (cadr (nth 2 x)))
-             (var-pos (nth 4 x)))  ;; pair: start and end of var decl
-
-        ;; The simple string= test will give a false positive if there's
-        ;; a foreach loop variable in a prior
-        ;; foreach loop with the same name as the one the user
-        ;; wants completion on.
-        ;;
-        ;; This is only an issue with two or more foreach loops, each of
-        ;; which create a separate naming scope, and which have the same
-        ;; variable name.  All those foreach variables will be reported
-        ;; as "local variables" by semantic. But, not all of them are in
-        ;; scope for the completion we're performing right now.
-        ;;
-        ;; This needs to do something more intelligent with
-        ;; the declaration. If I had a way to interrogate the scope of
-        ;; the variable decl, that would help. But right now I don't have
-        ;; that.
 
-        ;; I think I need a better understanding of the semantic.el
-        ;; package.
-        ;; =======================================================
+(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))))
 
-        ;; if this decl ends *before* the point at which the user is
-        ;; asking for completion.
-        (if (<  (elt var-pos 1) opoint)
 
-            ;; 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.
-                  ;;
-                  ;; For now, it will not handle:
-                  ;;
-                  ;;  - var that depends on a method argument
-                  ;;  - var whose initialization depends on an instance var
-                  ;;  - var decls in foreach loops
-                  ;;
-
-                  ;; if the type of the variable is "var"
-                  (if (string= var-type "var")
-                      (let* ((this-decl
-                              (buffer-substring-no-properties (elt var-pos 0) 
(elt var-pos 1)))
-
-                             (containing-type (cscomp-get-current-class))
-                             (member-list (cscomp-get-members-of-class 
containing-type))
-                             (name-of-containing-type  (car containing-type))
-
-                             (inferred-type
-                              (cscomp-get-var-type-given-decl
-                               (concat prior-var-decls " " this-decl)
-                               decl-count
-                               name-of-containing-type
-                               
(cscomp-produce-csharp-arglist-block-from-dbrecord 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 "cscomp-qualify-local-var: found %s (%s)"
-                            symbol var-type)
-                  (setq result (list var-type var-pos)))
-
-              ;; else - remember it. We may need it later
-              (let* ((this-var-decl
-                      (buffer-substring-no-properties (elt var-pos 0) (elt 
var-pos 1)))
-                     (tokens (split-string this-var-decl "[ \t]" t)))
-
-                ;; include decl in prior decls if not "foreach(var foo in X)"
-                (if (or (< (length tokens) 4)
-                        (not (string= (nth 3 tokens) "in")))
-                    (setq prior-var-decls (concat prior-var-decls " " 
this-var-decl)
-                          decl-count (1+ decl-count))
-
-                  ;; else - it's a foreach loop
-
-                  ;; If performing completion on a var within the loop that
-                  ;; depends on the loop variable, then we need to infer
-                  ;; the type of the foreach loop variable here.
-                  ;;
-                  ;; But, I'm punting.
+(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 locals (cdr locals)))
+
+      (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.
 
-(defun cscomp-qualify-instance-var (symbol)
-  "Use the semantic lex/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.
+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-start-stripped-semantic)
-  ;;(semantic-lex (point-min) (point-max) 100)
-  (let ((ivars (cscomp-instance-vars))
-        (result nil))
-    (while (and ivars (not result))
-      (let* ((x (car ivars))
-             (var-name (car x))
-             (var-type (cadr (nth 2 x)))
-             (var-pos (nth 4 x)))
-        (if (string= var-name symbol)
-            (progn
-              (cscomp-log 2 "cscomp-qualify-instance-var: found %s (%s)"
-                       symbol var-type)
-            (setq result (list var-type var-pos))))
-      (setq ivars (cdr ivars))))
-    result))
+  (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-start-stripped-semantic ()
-  "Enable a stripped-down semantic for usage with csharp-completion.
-Semantic is very ambitious and tries to do many things, including
-predictive completion, modified code formatting, and other
-things.  We don't want all that for this simple completion
-module. So this method starts a stripped-down version of
-semantic.
+(defun cscomp-pos-at-line-col (position)
+  "Return the char position at the given line/column POSITION,
+which is of the form (LINE . COLUMN).
 
 "
-  (interactive)
+  (let ((line (nth 0 position))
+        (column (nth 1 position)))
+    (save-excursion
+      (goto-char (point-min))
+      (forward-line (- line 1))
+      (+ (point) (- column 1)))))
 
-  (if (null semantic-load-system-cache-loaded)
-      (progn
-        ;;(semantic-lex (point-min) (point-max) 100)
-        (semantic-fetch-tags)
-        (global-semantic-idle-scheduler-mode 1)
-        ;;(global-semanticdb-minor-mode 1)
-        ;; This loads any created system databases which get linked into
-        ;; any searches performed.
-        (setq semantic-load-system-cache-loaded t)
-        )))
 
 
 
+(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'.
 
-;;     (let (start
-;;           varname
-;;           (curcar (char-before))
-;;           found
-;;           (original-point (point))
-;;           intermediate-point
-;;           beg-point
-;;           first-part
-;;           second-part
-;;           (bracket-count 0)
-;;           (paren-count 0))
-;;
-;;
-;;       (while (null found)
-;;         (cond
-;;
-;;          ;; car is a-z, A-Z 0-9 or greater than 127, or slash or underscore
-;;          ((or (and (>= curcar ?a) (<= curcar ?z))
-;;               (and (>= curcar ?A) (<= curcar ?Z))
-;;               (and (>= curcar ?0) (<= curcar ?9))
-;;               (>= curcar 127)
-;;               (member curcar '(?_ ?\\ )))
-;;           ;; back up!
-;;           (forward-char -1))
-;;
-;;          ;; curchar is a dot
-;;          ((eq ?. curcar)
-;;           (setq found (point)))
-;;
-;;          ;; else
-;;          (t
-;;           (setq found t)))
-;;
-;;
-;;         (setq curcar (char-before)))
-;;
-;;       ;; we've backed-up to...the nearest dot or non- alphanumeric char.
-;;
-;;
-;;       ;; ??
-;;       (setq intermediate-point (point))
-;;
-;;
-;;       (if (not (eq t found))  ;; not t means we found a dot
-;;           (progn
-;;
-;;             ;; get the char before
-;;             (setq curcar (char-before))
-;;             (while (or (and (>= curcar ?a) (<= curcar ?z))
-;;                        (and (>= curcar ?A) (<= curcar ?Z))
-;;                        (and (>= curcar ?0) (<= curcar ?9))
-;;                        (>= curcar 127)
-;;                        (and (eq curcar ? ) (or (< 0 paren-count) (< 0 
bracket-count)))
-;;                        (member curcar '(?\. ?\_ ?\\ ?\( ?\) ?\, ?\[ ?\])))
-;;               (cond
-;;                ((eq curcar ?\) )
-;;                 (setq paren-count (1+ paren-count)))
-;;                ((eq curcar ?\( )
-;;                 (setq paren-count (1- paren-count)))
-;;                ((eq curcar ?\] )
-;;                 (setq paren-count (1+ bracket-count)))
-;;                ((eq curcar ?\[ )
-;;                 (setq paren-count (1- bracket-count))))
-;;               (forward-char -1)
-;;
-;;               (setq curcar (char-before)))
-;;
-;;
-;;             (setq beg-point (point))
-;;
-;;             (set-marker cscomp-current-beginning intermediate-point)
-;;
-;;             (set-marker cscomp-current-end original-point)
-;;
-;;             (setq first-part (buffer-substring-no-properties beg-point (- 
intermediate-point 1)))
-;;
-;;             (setq first-part (cscomp-isolate-to-complete first-part))
-;;
-;;             (string-match " *\\(.*\\)" first-part)
-;;
-;;             (setq first-part (substring first-part (match-beginning 1) 
(match-end 1)))
-;;
-;;             (setq second-part (buffer-substring-no-properties 
intermediate-point original-point))
-;;
-;;             (list first-part second-part))
-;;
-;;         nil))))
+"
+  (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-build-clist-for-ns (nsinfo)
+
+(defun cscomp-completion-list-for-ns (nsinfo)
   "Build a completion list from the NSINFO list, as returned by the
 Ionic.Cscomp.Utilities.GetCompletionsForNamespace function.
 
@@ -1482,8 +1489,10 @@ Then the return value is like this:
    \"Comparer<T1> | (type)\"
    \"Dictionary<T1,T2> | (type)\"
    \"EqualityComparer<T1> | (type)\"
-   \"Something1 | (type)\"
-   \"Something2`2 | (type)\")
+   \"Something1 | (namespace)\"
+   \"Something2`2 | (namespace)\")
+
+It's just a transformation from one data format to another.
 
 "
   (let* ((typelist (cadr (cadr nsinfo)))
@@ -1563,7 +1572,7 @@ modified.
           (setf (nth n clist) new-name))
       ;; the following will affect the string in the list
       (string-replace-char cur-elt ?+ ?.)
-      (setq n (1+ n))))
+      (incf n)))
   clist)
 
 
@@ -1585,7 +1594,7 @@ to  (Method) public (System.Converter<T,TOutput> 
converter) returns List<TOutput
 
 
 
-(defun cscomp-build-clist-for-type (typeinfo)
+(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.
@@ -1622,7 +1631,7 @@ The output looks like this:
         (fields  (caddr (cddr typeinfo)))
         modifiers)
 
-    (cscomp-log 2 "cscomp-build-clist-for-type: typename(%s)" tname)
+    (cscomp-log 3 "completion-list-for-type: typename(%s)" tname)
 
     (while props
       (let ((one-prop (car props) ) )
@@ -1694,14 +1703,14 @@ The output looks like this:
       (setq fields (cdr fields)))
 
 
-    (cscomp-log 3 "cscomp-build-clist-for-type: result: "
+    (cscomp-log 2 "completion-list-for-type: result: "
               (prin1-to-string result))
     ;;(print result (get-buffer "*Messages*"))
     result))
 
 
 
-(defun cscomp-build-clist-for-ctors (ctor-info)
+(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.
@@ -1730,12 +1739,10 @@ for use in a popup menu.
 
 "
   (let (result
-        (tname   (car ctor-info))
-        (ctors   (cadr (caddr ctor-info)))
-        ;;(methods (cadddr typeinfo))
-        )
+        (tname (car ctor-info))
+        (ctors (cadr (caddr ctor-info))))
 
-    (cscomp-log 2 "cscomp-build-clist-for-ctor: typename(%s)" tname)
+    (cscomp-log 2 "completion-list-for-ctors: typename(%s)" tname)
 
     (while ctors
       (let* ((one-ctor (car ctors))
@@ -1755,38 +1762,22 @@ for use in a popup menu.
                 "()" )))
         (setq result
               (append (list
-                       (list
-                        tname  ;; name of the ctor
-
-                        ;; description for this ctor
-                        (concat "(Constructor) "
-                                modifiers  ;; modifiers on this prop
-                                " "
-                                params
-                                )))
+                       (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 "cscomp-build-clist-for-ctors: result: "
-              (prin1-to-string result))
+    (cscomp-log 3 "completion-list-for-ctors: result: "
+                (prin1-to-string result))
     result))
 
 
 
-;; (defun cscomp-build-information-for-completion (lst)
-;;   (let ((result (concat (car (cdr lst)) " " (car lst) "(")))
-;;     (setq lst (cdr (cdr lst)))
-;;     (while lst
-;;       (setq result (concat result (car lst)))
-;;       (setq lst (cdr lst))
-;;       (if lst
-;;           (setq result (concat result ", "))))
-;;     (setq result (concat result ")"))
-;;     result))
-
-
-
-
 ;; (defun cscomp-popup-xemacs-completion-menu (completion-list)
 ;;   (let* ((items
 ;;        (sort
@@ -1830,24 +1821,11 @@ for use in a popup menu.
              (string< e1 e2)))))
 
 
-;; (defun cscomp-sort-completion-list (lst)
-;;  ;;  "sort LST in place."
-;;   (sort lst
-;;         '(lambda (e1 e2)
-;;            (if (consp e1) ;; is the list elt a consp?
-;;                ;; yes, we're completing on a type. Sort on the car of that 
list
-;;                (string< (car e1) (car e2))
-;;              ;; no, we're completing on a namespace or local var.
-;;              ;; The element should be a string.  Sort on it directly.
-;;              (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-build-clist-for-ns'.
+`cscomp-completion-list-for-ns'.
 "
   (let ((result nil))
     (while lst
@@ -1879,7 +1857,7 @@ 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-build-clist-for-type'.
+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.
@@ -1889,6 +1867,8 @@ 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:
@@ -1922,7 +1902,7 @@ FRAGMENT are returned.
                              (string= fragment member-name)
                            (equal 0 (string-match fragment member-name))))))
 
-        (cscomp-log 3 "cscomp-find-all-type-completions, looking at %s %s"
+        (cscomp-log 4 "find-all-type-completions, looking at %s %s"
                   (prin1-to-string candidate)
                   (if is-match "MATCH" ""))
 
@@ -1931,15 +1911,12 @@ FRAGMENT are returned.
 
       (setq lst (cdr lst)))
 
-    (cscomp-log 3 "cscomp-find-all-type-completions, result: %s"
+    (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)
-    ))
-
-
+    (cscomp-sort-completion-list result)))
 
 
 
@@ -1966,57 +1943,86 @@ FRAGMENT are returned.
 
 
 (defun cscomp-map-primitive-type (type)
-"Maps the type to the expanded name of the  type, and returns that
-expanded name. For example, bool => 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 )
-    nil ))
-
-
+  "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 opoint beginning-of-token1)
+(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
+SPLIT is a list of (TOKEN1 TOKEN2), as returned from
 `cscomp-split-by-dots'.
 
-OPOINT is the point at which the user has requested completion.
-
-If the user has typed something followed by a dot, followed by an
-optional fragment after the dot, then TOKEN1 may be a C#
-namespace or class, or a variable name, or explicitly, \"this\" .
-TOKEN2 may be the empty string, or a fragment of a name.  The
-goal is to find a completion for these two things.
-
-Example: if SPLIT is (\"System\" \"Diag\") then the returned
-completion list will contain \"Diagnostics\".
-
-If the completion being requested is on a type, OPOINT is used to
-determine whether to present type names, or actual constructors.
-Do the latter if the new keyword precedes the
-thing-to-be-completed.
+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 "cscomp-find-completion-for-split: A: '%s' '%s'"
+  (cscomp-log 2 "find-completion-for-split: A: '%s' '%s'"
             (car split) (cadr split))
 
-  ;;
-  ;; p1 is what precedes the final dot, p2 is what follows.
-  ;; When there is no dot, p1 is nil.
+
+  ;; 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:
@@ -2034,242 +2040,330 @@ thing-to-be-completed.
   ;;
   ;; 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
+  ;;    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.
   ;;
-  ;; 5. p1 is the name of a type, like System.Console, and p2 is something.
+  ;; 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.
   ;;
-  ;; 6. p1 is the name of a primitive type, like byte or int.
+  ;; 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.
   ;;
-  ;; 7. others?
+  ;; 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.
+  ;; 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 parse results from semantic to find fields/props/methods.
+  ;; use the source code analysis results to find fields/props/methods.
   ;;
 
-  (let* ((p1 (car split))
-         (p2 (cadr split))
+  (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    (cscomp-qualify-local-var p1 opoint))
-         (is-instance-var (cscomp-qualify-instance-var p1))
-         (is-func         (string-match "($" p2))  ;; open-paren
-         (is-ctor         (and                     ;; constructor
-                           (null p1)
-                           (string-match "^\\([ \t\n\r\f\v]*new[ 
\t\n\r\f\v]+\\)\\(.+\\)$" p2)))
-         p1-flavor
-         p1-type
-         is-static
-         r)
-
-    (if is-ctor
-        ;; reset the beginning marker
-        (progn
-          (set-marker cscomp-current-beginning
-                      (+ cscomp-current-beginning
-                         (match-end 1)))
-
-          ;;(string-match "^\\([ \t]*new[ \t]+\\)\\(.+\\)$" p2)
-          ;; rely on most recent string-match context being for is-ctor
-          (setq p2 (substring p2 (match-beginning 2)))))
-
-
+         (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 static method/prop/field on a byte, int, char, etc.
-      (cscomp-log 3 "cscomp-find-completion-for-split: is-primitive")
-      (setq p1-flavor "type"
+      ;; 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
-      ;; method, property, or field on  a local variable.
-      (cscomp-log 3 "cscomp-find-completion-for-split: is-local-var")
-      (setq p1-flavor "type"
+      ;; 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 "cscomp-find-completion-for-split: is-instance-var")
-      (setq p1-flavor "type"
+      (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 p1-flavor "this"))
-
-
-     ((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 p1-flavor "namespace"
-                       p1-type (and
-                                (string-match "^\\(.+\\)\\..+$" (cadr r))
-                                (match-string 1 (cadr r)))
-                       p1 p1-type)
-               (setq p1-flavor "local")))
-            (t
-             (setq p1-flavor "local"))))
-
-
-     (is-ctor
-      (setq p1-flavor "mixed")
-      (if (null p1)
-          (setq p1 p2)))
-
-
-;;     ((and (null p1)   ;; no prefix.
-;;        (t
-;;         ;; It's not a ctor or static method.
-;;         ;; Maybe it's completion on a known typename or namespace.
-;;         (setq p1-flavor "mixed"))))
+      (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 p1-flavor (car r))
-
-               (if (string= p1-flavor "unknown")
-                 ;; assume p1 is an expression.  Try to infer it's type.
-                   (let ((inferred-type
-                         (cscomp-get-var-type-given-decl (concat "var x = " p1 
";")
-                                                          0
-                                                          "NoMatter"
-                                                          ""
-                                                          "")))
-                         (if (string= (car inferred-type) "type")
-                             (setq p1-type (cadr inferred-type)
-                                   p1-flavor "type")))
+      (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)))
 
-               ;; name qualification was successful
-               (setq p1-type p1
-                     is-static t)))) ;; if it's a type, we want static f/m/p 
only
+                (if inferred-type-info
+                    (setq p1-type
+                          (or (cscomp-map-primitive-type (car 
inferred-type-info))
+                              (car inferred-type-info))
+                          cflavor "type")))
 
-            (t
-             (error "qualify-name returns invalid results.")))))
+            ;; 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 "cscomp-find-completion-for-split: B: p1(%s,%s) p2(%s) 
flav(%s)"
-              p1 (if p1 p1-type "--")  (prin1-to-string p2) p1-flavor)
+    (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)
 
-    ;; now collect completion options depending on the "flavor" of p1:
-    ;; type == completing on m/f/p for a type, possibly with a fragment.
-    ;;         p1 holds the typename from the buffer, could be partially 
qualified.
-    ;;         p1-type holds the fully qualified type name. p2 holds the 
fragment.
-    ;; namespace == completing on a  namespace.  The result can be a child
-    ;;         namespace or a type within a namespace.
-    ;; this == completing on a m/f/p of the local instance
-    ;; local == completing on a m/f/p of local variables or method args
-    ;; mixed == could be either a typename or a namespace name. This is
-    ;;         the case when p1 is partial, and there is no dot.
+      (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
+        ;;
 
-    (cond
+        ;; 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)
 
-     ((string= p1-flavor "type")
-      (let* ((type-info (cscomp-get-typeinfo p1-type))
-            (full-list (cscomp-build-clist-for-type type-info)))
-      (cond
+        (cscomp-log 2 "find-completion-for-split, flav(%s)" cflavor)
 
-       (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 "cscomp-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))
+        (cond
 
-          (cscomp-log 3 "cscomp-find-completion-for-split: [%s]"
-                    (prin1-to-string cscomp-current-list))))))
+         ((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= p1-flavor "namespace")
-      (cscomp-log 2 "cscomp-find-completion-for-split, is-func(%s) bot(%d)"
-                is-func beginning-of-token1)
-      (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)))
+         ((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-build-clist-for-ctors ctor-info)))
+                 (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 ;; complete on a type name, or child namespace
-        (let* ((type-list (cscomp-get-completions-for-namespace p1))
-               (full-list (cscomp-build-clist-for-ns type-list)))
 
-          (setq cscomp-current-list
-                (cscomp-find-all-ns-completions p2 full-list))
-          (cscomp-log 3 "cscomp-find-completion-for-split: [%s]"
-                    (prin1-to-string cscomp-current-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= p1-flavor "local")
-      (let ((instance-vars (cscomp-matching-instance-vars p2))
-            (locals (cscomp-matching-local-vars p2)))
-        (setq cscomp-current-list
+         ((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= p1-flavor "this")
-        (setq cscomp-current-list
-              (cscomp-matching-instance-members p2)))
-
-
-     ((string= p1-flavor "mixed")
-      (setq r (cscomp-get-matches p2))
-      (if (listp r)
+         ((string= cflavor "this")
           (setq cscomp-current-list
-                (mapcar '(lambda (listitem)
-                           (list
-                            ;; the thing to insert
-                            (if (and p1 (string-match (concat "^" p1)
-                                                      (cadr listitem)))
-                                (cadr listitem)
-                              (string-match (concat "\\.\\(" p2 ".*\\)") (cadr 
listitem))
-                              (match-string 1 (cadr listitem)))
-
-                            ;; the description that will be visible in the menu
-                            (concat (cadr listitem) " | (" (car listitem) ")")
-                            ))
-                        r))
-        (error "Cannot complete.")))
+                (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.")))))))
 
-     (t
-      (cscomp-log 1 "cscomp-find-completion-for-split, unknown flavor (%s)"
-                p1-flavor)
-      (error "Cannot complete.")))))
 
 
 
@@ -2357,8 +2451,8 @@ to that function.
 (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 either a (NAME DESCRIP) pair, or
-a simple NAME.
+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
@@ -2372,11 +2466,11 @@ 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
-potentially something more interesting.
+something suitable for use within a menu.
 
 "
   (if (consp clist-item)
-      (let ((meth-or-prop-name (car 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
@@ -2395,13 +2489,13 @@ potentially something more interesting.
                                                         (match-beginning 1)
                                                         (match-end 1))
                                              "Constructor")
-                                    (if (string-match ".+\\." 
meth-or-prop-name)
-                                        (substring meth-or-prop-name
+                                    (if (string-match ".+\\." mpfv-name)
+                                        (substring mpfv-name
                                                         (match-end 0))
-                                      meth-or-prop-name)
-                                  meth-or-prop-name)))
+                                      mpfv-name)
+                                  mpfv-name)))
 
-            (cons (concat meth-or-prop-name " | " descrip)
+            (cons (concat mpfv-name " | " descrip)
                   (if (fboundp 'yas/expand-snippet)
                       (cscomp-yasnippet-for-arglist name-to-insert arglist)
                     (concat name-to-insert arglist)))))
@@ -2409,8 +2503,8 @@ potentially something more interesting.
          (t
           ;; The completion is not a method - just
           ;; insert the name of the field/prop as a string.
-          (cons (concat meth-or-prop-name " | " descrip)
-                meth-or-prop-name))))
+          (cons (concat mpfv-name " | " descrip)
+                mpfv-name))))
 
     (cons clist-item clist-item)))
 
@@ -2433,7 +2527,8 @@ in `cscomp-current-list' .
   ;; is the name of the method/prop/field, and DESCRIP is a string
   ;; description.
   ;;
-  ;; For a namespace, the clist is a list of strings.
+  ;; 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.
   ;;
@@ -2441,14 +2536,13 @@ in `cscomp-current-list' .
   (let* ((menu-map (cons "ignored"
                          (mapcar 'cscomp-get-menu-item-for-clist-item
                                  cscomp-current-list)))
-         (menu-result (cscomp-popup-menu
+         (menu-result (cscomp--popup-menu
                        (list (or title "Completions...") menu-map))))
 
-    (cscomp-log 1 "menu-result:  %s" (prin1-to-string menu-result))
+    (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
@@ -2483,6 +2577,7 @@ in `cscomp-current-list' .
       (selected-frame)
     (selected-window)))
 
+
 (defun cscomp-current-row ()
   "Return current row number in current frame."
   (if (fboundp 'window-edges)
@@ -2497,10 +2592,14 @@ in `cscomp-current-list' .
         (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 (car (cdr pixel-pos)) (cdr (cdr pixel-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)
@@ -2533,21 +2632,21 @@ DX and DY specify optional offsets from the top left of 
the glyph."
     (list 'mouse-1 pos)))
 
 
-(defun cscomp-popup-menu (menu-data)
+(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))
-             (fake-event-props  '(button 1 x 1 y 1)))
-        (setq fake-event-props (plist-put fake-event-props 'x x-pos))
-        (setq fake-event-props (plist-put fake-event-props 'y y-pos))
+      (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 fake-event-props)))
+                    (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 2 20)
+                      (cscomp-posn-at-point-as-event nil nil 42 20)
                     (list (cscomp-get-point-pixel-pos) (selected-window)))
                    menu-data)))
 
@@ -2579,7 +2678,7 @@ deletes the text between the markers, before inserting 
the completion.
 
 "
   (let (elem)
-    (setq cscomp-current-list-index (1+ cscomp-current-list-index))
+    (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
@@ -2588,35 +2687,30 @@ deletes the text between the markers, before inserting 
the completion.
     (cscomp-log 3 "complete-cycle-candidates: looking at %s" (prin1-to-string 
elem))
 
     (cond
+
      ((listp elem)
-      (if (car elem)
-          (let ((thing-to-insert
-                 (car elem))
-                ;;(substring (car elem) (length cscomp-current-fragment)))
-                )
-            (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 (format "No completion at this point!(cycle)"))))
+      (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)
-            ;;(substring elem (length cscomp-current-fragment)))
-            )
+      (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)))
-     )))
-
+        (message "cscomp: %s" elem))))))
 
 
 
@@ -2674,59 +2768,44 @@ that lets you select the desired completion from a 
popup menu.
 
         (if (not (null split))
             (progn
-              ;; set markers
-              (cscomp-log 1 "complete-at-point: reset begin,end to (%d,%d)"
-                        (- (point) (length (cadr split)))
-                        (point))
-
-              ;; beginning: right after the dot (if there is one)
-              (set-marker cscomp-current-beginning
-                          (- (point) (length (cadr split))))
-
-              (set-marker cscomp-current-end (point))
-              (cscomp-find-completion-for-split split (point) (car 
parse-result))
+              (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, the inserted
-thing is a parameterized snippet, a template that can then be filled in
-by the user.
+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.
+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))))
 
-    ;; 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)
-
     (if (not (null split))
         (progn
-          ;; set markers
-          (set-marker cscomp-current-beginning (- (point) (length (cadr 
split))))
-          (set-marker cscomp-current-end (point))
-
-          (cscomp-find-completion-for-split split (point) (car parse-result))
+          (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) "...")))
+              (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 "")))
@@ -2740,55 +2819,83 @@ lets you cycle through the potential completions at 
point.
 
 
 
-;; ;; =======================================================
-;; ;; Adding a new semantic tag for "namespace".
-;; ;;
-;; ;; This turned out to be much harder that it should be.
-;; ;;
-;; ;; Apparently there are special handling for tags of type 'type,
-;; ;; So, for now, punt on doing it this way.
-;; ;;
-;; ;; =======================================================
-;; ;;
-;; (defsubst semantic-tag-new-namespace (name members &rest attributes)
-;;   "Create a semantic tag of class 'namespace.
-;; NAME is the name of this namespace.
-;; MEMBERS is a list of strings or semantic tags representing the
-;; elements that are contained within the namespace.
-;; ATTRIBUTES is a list of additional attributes belonging to this tag."
-;;   (apply 'semantic-tag name 'namespace
-;;          :members members
-;;          attributes))
-;;
-;;
-;;
-;; ;; We want this:
-;; ;;
-;; ;; (defun semantic-tag-components-default (tag)
-;; ;;   "Return a list of components for TAG.
-;; ;; Perform the described task in `semantic-tag-components'."
-;; ;;   (cond ((semantic-tag-of-class-p tag 'type)
-;; ;;          (semantic-tag-type-members tag))
-;; ;;         ((semantic-tag-of-class-p tag 'namespace)
-;; ;;          (semantic-tag-type-members tag))
-;; ;;         ((semantic-tag-of-class-p tag 'function)
-;; ;;          (semantic-tag-function-arguments tag))
-;; ;;         (t nil)))
-;;
-;; ;; we'll settle for this:
-;;
-;; (defadvice semantic-tag-components-default (after
-;;                                             cscomp-advice-1
-;;                                             (tag)
-;;                                             activate compile)
-;;
-;;   (cond ((semantic-tag-of-class-p tag 'namespace)
-;;          (semantic-tag-type-members tag))
-;;         (t ad-return-value)))
+;; ========================================================================
+;; 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.
 
-(provide 'csharp-completion)
+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
index aae6a26..0e4afbb 100644
--- a/csharp-shell.el
+++ b/csharp-shell.el
@@ -1,24 +1,25 @@
 ;;; csharp-shell.el --- run PowerShell to assist with c# completion.
 ;;
-;; Author:     Dino Chiesa <dpchiesa@hotmail.com>
-;; Created:    10 Apr 2008
-;; Modified:   May 2010
-;; Version:    0.2
-;; Keywords:   powershell C# shell
-;; X-URL:      ??
+;; 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.  It is part of cscomp.  (C# completion).
+;;   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 custom utility assembly 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.
+;;   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
@@ -42,11 +43,14 @@
 ;;   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 known as Intellisense in Microsoft's Visual Studio.
+;;   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, relying on the use of a shell.
+;;   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.
 ;;
 ;;   ------------
 ;;
@@ -55,6 +59,7 @@
 ;;
 
 
+(require 'cscomp-base)
 (require 'powershell)
 
 (defcustom csharp-shell-location-of-util-dll  nil
@@ -63,9 +68,10 @@ 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.  For example,
+the file cscompUtilities.dll.  It should use fwd-slashes and should include
+the trailing slash.  For example,
 
-      \"c:\\users\\fred\\elisp\\cscomp\"
+      \"c:/users/fred/elisp/cscomp/\"
 
 "
   :group 'cscomp
@@ -78,7 +84,7 @@ on Shell startup."
   :group 'cscomp
   :type 'integer)
 
-(defcustom csharp-shell-exec-timeout 9
+(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. "
@@ -95,49 +101,6 @@ the time to wait between chunks of response. "
   "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.")
 
 
-(defvar cscomp-log-level 0
-  "The current log level for C# completion operations.  0 = NONE, 1 = Info, 2 
= VERBOSE, 3 = DEBUG. ")
-
-
-(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 "%s" msg)
-        )))
-
-
-(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--internal (&optional display-buffer)
-  (if (not (comint-check-proc csharp-shell-buffer-name))
-      ;; then
-      (let (version)
-        (message "Starting CscompShell...")
-        (setq version (csharp-shell--start))
-        (message "CscompShell v%s is now running..." version)
-       )
-    ;; else
-    (when display-buffer
-      (message "CscompShell is already running."))
-    )
-  )
-
-
-;; (defvar csharp-shell--reply nil
-;;   "Internal use only.")
 
 
 
@@ -164,31 +127,38 @@ return value is the collected text.
         (let (reply tmp)
 
           (with-current-buffer csharp-shell-buffer-name
-            (cscomp-log 2 "csharp-shell-exec: Sending: %s" expr)
+            (cscomp-log 3 "csharp-shell-exec: Sending: %s" expr)
             (setq reply
                   (powershell-invoke-command-silently proc expr 
csharp-shell-exec-timeout)))
 
 
-          (if (or (null reply)
-                  (string-match "// Error:" reply))
-              (progn
-                (cscomp-log 1
+          (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.")))
+              (error "CscompShell eval error. See messages buffer for 
details."))))
 
 
           (if eval-return
               (if (and reply (not (string= reply "")))
                   (progn
-                    (cscomp-log 2 "csharp-shell-exec: evaluating reply: '%s'" 
reply)
+                    (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 2 "csharp-shell-exec: eval result(%s)" 
(prin1-to-string tmp)) ;; can be nil
+                          (cscomp-log 3 "csharp-shell-exec: eval result(%s)" 
(prin1-to-string tmp)) ;; can be nil
                           tmp)
                       nil))
 
@@ -210,8 +180,10 @@ return value is the collected text.
 (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 with the evaluate-return option set to
-t."
+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))
 
 
@@ -283,73 +255,155 @@ t."
 "
 
   (let* ((cscompshell-buffer (powershell
-                            csharp-shell-buffer-name
-                            csharp-shell-prompt-string))
+                              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" ))
+                         "idontknow/" )
+                        "CscompUtilities.dll" ))
          result
          version)
 
-    (if 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 .
-
-          (setq result
-                (powershell-invoke-command-silently
-                 proc
-                 (concat "[System.Reflection.Assembly]::LoadFrom('" 
dll-location "')")
-                 6.5))
-
-          (if (string-match "^Exception .*: \"\\(.+\\)\"" result)
-              (let ((message (substring result (match-beginning 1) (match-end 
1))))
-              (error (concat "error: " message))))
-
+    ;; xxxx
 
-          ;; get the version number
-          (setq version
-                (powershell-invoke-command-silently
-                 proc
-                 "[Ionic.Cscomp.Utilities]::Version()"
-                 2.9))
+    (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.
 
-          (if version
-              (setq version (substring version 1 -1)))
+        ;; load the CscompUtilities DLL .
 
-          ;; If the user exits, we won't ask whether he wants to kill the 
CscompShell.
-          (set-process-query-on-exit-flag proc nil)
+        (cscomp-log 2 "CscompShell: the powershell process is running...")
 
-          ;;(comint-simple-send proc "prompt\n") ;; shouldn't need this
+        (setq result
+              (powershell-invoke-command-silently
+               proc
+               (concat "[System.Reflection.Assembly]::LoadFrom('" dll-location 
"')")
+               6.5))
 
-          ;; 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)
+        (cscomp-log 2 "CscompShell: load dll result: %s" result)
 
-          ;; 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)
+        (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
diff --git a/flymake-for-csharp.el b/flymake-for-csharp.el
deleted file mode 100644
index 431fead..0000000
--- a/flymake-for-csharp.el
+++ /dev/null
@@ -1,927 +0,0 @@
-;;; flymake-for-csharp.el --- C# mode derived mode
-;;
-;; Author:     Dino Chiesa
-;; Version:    1.2
-;; Modified:   2010 May 10
-;; Keywords:   c# flymake
-;;
-;; This code is distributed under the MS-Public License.
-;; See http://opensource.org/licenses/ms-pl.html
-;;
-;; last saved
-;; Time-stamp: <2010-May-11 14:33:13>
-
-
-;; ==================================================================
-;;
-;; This module provides tweaks to the flymake minor mode, to allow it to
-;; work with csharp.
-;;
-;; Flymake is built-in to emacs.  It periodically compiles an active
-;; buffer when the minor mode is enabled, and then flags or highlights
-;; lines that cause errors or warnings during the compile as you
-;; edit. It is analogous to the red-squigglies you get in Visual Studio,
-;; highlighting syntax errors or other compile problems.
-;;
-;; This elisp module defines a set of tweaks of flymake, to allow it to
-;; work with C# on Windows.  flymake-for-csharp depends on a makefile or
-;; msbuild file of well-known name, with some well-known settings, in
-;; order to work.  These are documented below.
-;;
-;; ==================================================================
-;;
-;; To use:
-;;
-;; 1. put flymake-for-csharp.el on your load path.
-;;
-;; 2. somewhere in your .emacs, place this:
-;;       (require 'flymake-for-csharp)
-;;
-;; 3. Add this to your csharp-mode-hook function:
-;;       (flymake-mode)
-;;
-;; 4. specify how you want to use flymake, via these variables:
-;;
-;;     flymake-for-csharp-netsdk-location
-;;     flymake-for-csharp-dotnet-location
-;;     flymake-for-csharp-buildfile-alist
-;;     flymake-for-csharp-grep-pgm
-;;     flymake-for-csharp-csc-arguments
-;;
-;;
-;;    ...and by possibly adding special check-syntax targets in
-;;    your makefile or msbuild file.
-;;
-;; Full details are provided  below.
-;;
-;;
-;; Intro:
-;;
-;; Flymake is a language-neutral mode that periodically invokes a
-;; source-code compiler to check the syntax of the currently-
-;; being-edited buffer.
-;;
-;; flymake-for-csharp is a C#-specific extension of flymake-mode, and
-;; provides the logic for invoking the C# compiler to do the syntax
-;; check on the currently-being-edited buffer.
-;;
-;;
-;; When the flymake mode timer fires, it calls into the
-;; flymake-for-csharp logic.  flymake-for-csharp copies the contents of
-;; the current C# buffer to a temporary source file, then invokes the C#
-;; compiler on that temporary source file.  flymake-for-csharp can do
-;; this in one of 3 ways:
-;;
-;; - using the csc.exe compiler directly;
-;; - using a makefile and invoking nmake
-;; - using a msbuild file and invoking msbuild.exe
-;;
-;;
-;; Which option you choose depends on your requirements.  If the .cs
-;; file you're editing is a standalone module, you can compile it with a
-;; simple invocation of csc.exe.  If the module being edited must be
-;; compiled with other source modules in order to compile correctly, you
-;; will use nmake or msbuild, as you prefer.
-;;
-;; To allow flymake-for-csharp to work with either the nmake or msbuild
-;; options, you need to specify a particular well-known target in your
-;; makefile, or in your msbuild file.
-;;
-;; Now, how to select the compile option:
-;;
-;;
-;; Option A: use the csc.exe compiler directly
-;; ============================================
-;;
-;; This is the simplest option, and also the most limited. With this
-;; option, flymake-for-csharp compiles the copy of the existing buffer
-;; using the csc.exe command-line compiler, and the arguments you
-;; provide, via the `flymake-for-csharp-csc-arguments' variable.
-;; Appended to that list of arguments will be the name of a temporary
-;; .cs file, with the contents of the currently-being-edited C# buffer.
-;; You should not include the name of the current .cs file in the
-;; `flymake-for-csharp-csc-arguments' variable, but you can specify the
-;; names of other .cs files that should be compiled *with* the current
-;; one.  The `flymake-for-csharp-csc-arguments' variable is only used
-;; with the direct csc.exe build option; it is not used when
-;; flymake-for-csharp invokes nmake or msbuild to do the syntax check.
-;;
-;; If you do no special setup, the direct csc.exe build will be used.
-;;
-;; Here's why: in deciding which build option to use, flymake-for-csharp
-;; searches the list of build files in
-;; `flymake-for-csharp-buildfile-alist' to find one appropriate for use
-;; for syntax checking, and uses the first one it finds. If no
-;; appropriate build files are found, flymake-for-csharp falls back to
-;; invoking the csc.exe compiler directly.
-;;
-;; To determine if a build file is appropriate, flymake-for-csharp uses
-;; these criteria:
-;;
-;;     1. the name of the makefile or msbuild file is on the special
-;;        variable, `flymake-for-csharp-buildfile-alist'
-;;
-;;     2. the makefile or msbuild file contains a special target
-;;        by a well-known name.  check-syntax for makefiles, and
-;;        CheckSyntax for msbuild files.
-;;
-;; If you do *nothing*, then these criteria won't be satisfied, and
-;; flymake-for-csharp will try to use csc.exe to check the syntax of
-;; your C# buffer.
-;;
-;; If you want to explicitly insure that flymake-for-csharp will use
-;; csc.exe to check the syntax of your C# buffer, then set
-;; `flymake-for-csharp-buildfile-alist' to nil, OR, insure that none of
-;; the build files in that list, exist in the directory where the .cs
-;; file resides, OR if they do exist, that the required build targets
-;; are not present in those build files.
-;;
-;; The compile-directly-with-csc.exe option is limited because
-;; flymake-for-csharp will use the same arguments with all .cs buffers.
-;; Often you want to compile .cs files differently.  Each project
-;; usually requires a different set of assemblies, for instance.  If you
-;; want to use flymake in a scenario like that, you'll want to rely on
-;; the nmake.exe or msbuild.exe options for flymake-for-csharp.
-;;
-;;
-;; Option B: use nmake and a makefile.
-;; ============================================
-;; If you want to use a makefile, you must:
-;;
-;; 1. configure the `flymake-for-csharp-netsdk-location' variable to
-;;    specify the location of the bin directory that contains nmake.exe.
-;;    Usually it is in one of the following places:
-;;
-;;    - the .NET 2.0 SDK directory
-;;      example: C:\Program Files\Microsoft SDKs\Microsoft .Net\v2.0
-;;    - the Visual Studio directory, if the VS install is the source of the 
.NET SDK
-;;      example: c:\Program Files\Microsoft Visual Studio 9\SDK\v2.0
-;;
-;;    example:
-;;      (setq flymake-for-csharp-netsdk-location "c:\\Program Files\\Microsoft 
Visual Studio 9\\SDK\\v2.0")
-;;
-;;    Notice that you should not append the bin subdir on the value of
-;;    flymake-for-csharp-netsdk-location.
-;;
-;;
-;; 2. set `flymake-for-csharp-buildfile-alist' to a list of filespecs
-;;    for names of makefiles. You can use wildcards.  The name of the
-;;    makefile must have the word "makefile" in it, or should end with
-;;    .mak.  flymake-for-csharp looks for files from the alist, in the
-;;    same directory as the currently-being-edited .cs file, where the
-;;    filename fits the constraint just described.
-;;
-;;    If the makefile exists, flymake-for-csharp searches within the
-;;    file for a make target by the name of "check-syntax" .  (This fixed
-;;    name is consistent with the use of flymake for C language source
-;;    files.).  If the makefile exists and contains the check-syntax make
-;;    target, flymake-for-csharp runs nmake.exe on it to check the
-;;    syntax of the currently-being-edited .cs file.
-;;
-;;    By default, `flymake-for-csharp-buildfile-alist' contains "makefile",
-;;    "flymake.mak" and "makefile.flymake".  If you put your check-syntax
-;;    target in a file by one of those names, then you won't need to
-;;    change the value of `flymake-for-csharp-buildfile-alist' .
-;;
-;;
-;;
-;; 3. Create the check-syntax target in the makefile. In the simplest
-;;    case, you compile only a single source module at a time.  The
-;;    target block to do syntax checking would look something like so:
-;;
-;;        check-syntax:
-;;           %windir%\Microsoft.NET\Framework\v3.5\csc.exe /t:module 
$(FLYMAKE_CHECK)
-;;
-;;    This works for standalone source modules; those that do not depend
-;;    on any other source modules.  If your source module depends on
-;;    particular assemblies, you could insert them on the CSC command line,
-;;    using the /R option, like so:
-;;
-;;        check-syntax:
-;;           $(_CSC) /t:module /R:foo.dll $(FLYMAKE_CHECK)
-;;
-;;
-;;    The target name MUST be "check-syntax". In the command that runs
-;;    for that target, you can run whatever commands you
-;;    like. Typically, you will invoke the c# compiler as appropriate.
-;;    You can use a make variable like $(_CSC) if one is defined in your
-;;    makefile.  If you use /target:netmodule, flymake-for-csharp will
-;;    delete any temporary .netmodule files that are created as part of
-;;    the syntax check.  If you don't, if for example you want to create
-;;    a DLL or EXE for some reason, you'll need to do your own cleanup
-;;    in the command block.
-;;
-;;    Flymake invokes nmake with several nmake macros defined on the
-;;    command line:
-;;
-;;        FLYMAKE_CHECK  - the name of the file to check.  This is a source
-;;                 file with a temporary name, copied from the current
-;;                 state of the buffer.  If you are editing Module.cs, then
-;;                 the value of this macro will be  Module_flymake.cs
-;;
-;;        FLYMAKE_ORIGINAL  - the name of the original file that is being
-;;                 checked for syntax.  In the above example, it will be
-;;                 Module.cs
-;;
-;;        FLYMAKE_SYNTAX_CHECK - set to 1
-;;
-;;    That covers the simple case. In more complex cases, there are a
-;;    set of other source files in a project that get compiled to a
-;;    single DLL, for example.  When editing one of those files, you'll
-;;    need to *exclude* the FLYMAKE_ORIGINAL file, and to *include* the
-;;    FLYMAKE_CHECK file, in the check-syntax make target. This can be
-;;    done with nmake macros, and inline files.
-;;
-;;    For example, suppose you have a project that compiles 3 source
-;;    files, Fribble,cs Zambda.cs Twoolie.cs, into a DLL. Regardless
-;;    which file you are currently editing in emacs, you want to compile
-;;    *the other two* along with the temporary copy of the currently-
-;;    being-edited file into a netmodule. You can do that like so:
-;;
-;;        CS_SOURCE=Fribble.cs Zambda.cs Twoolie.cs
-;;             ....
-;;        check-syntax :
-;;                <<flymake-build.cmd  $(CS_SOURCE)
-;;            SETLOCAL ENABLEDELAYEDEXPANSION
-;;            for %%I in (%*) do if NOT %%I == $(FLYMAKE_ORIGINAL) (
-;;               set filesToBuild=!filesToBuild! %%I
-;;            )
-;;            $(_CSC) /t:module $(FLYMAKE_CHECK) !filesToBuild!
-;;            ENDLOCAL
-;;        <<
-;;
-;;
-;;    Given that target in the makefile, all files EXCLUDING the
-;;    currently-being-edited file, but INCLUDING the temporary copy of
-;;    the currently-being-edited file, are compiled into a module.  The
-;;    double-angle-bracket signifies the use of a little-known feature
-;;    of nmake called in-line files.  The above nmake snippet causes
-;;    nmake to create a temporary .cmd file, and invoke it.  The .cmd
-;;    file includes the logic to exclude the original C# file from the
-;;    build, and include the temporary C# file into the build.
-;;
-;;    Putting the $(FLYMAKE_CHECK) file first on the csc line causes
-;;    the generated .netmodule file to have a name that allows
-;;    flymake-for-csharp to find it and delete it when flymake
-;;    finishes.
-;;
-;;    If you don't want to put a check-syntax make target into your main
-;;    makefile, you can alternatively put it into an alternative
-;;    makefile, for example "makefile.flymake" or "flymake.mak". Insure
-;;    that the filename you use is included as one element in the
-;;    variable `flymake-for-csharp-buildfile-alist'.
-;;
-;;
-;;
-;; ==================================================================
-;;
-;;
-;; Option C: use msbuild
-;; ============================================
-;;
-;; If you use msbuild, rather than nmake, specify the location of
-;; msbuild.exe via the `flymake-for-csharp-dotnet-location' variable,
-;; and insure that `flymake-for-csharp-buildfile-alist' contains a spec
-;; for a buildfile that contains the well-known target, CheckSyntax.
-;;
-;; As described above, Wildcards are allowed in the elements in the alist.
-;; After wildcard expansion, for each
-;; file in the list that has a name that includes "msbuild" or ends in
-;; .xml, or .csproj, flymake-for-csharp will search the file, and check
-;; for the well-known build target of "CheckSyntax" in the file. If that
-;; target is found, then flymake-for-csharp will use that as the msbuild
-;; file to do syntax checking.
-;;
-;; flymake-for-csharp insists on finding a build file that contains a
-;; target by the name of "CheckSyntax".  Also, the target name MUST be
-;; defined on the same line as the <Target> element, immediately
-;; following the element name like so:
-;;
-;;      <Target Name="CheckSyntax"  ....
-;;
-;; The reason for this restriction: flymake-for-csharp does a
-;; text-search in the build file for that well-known target name, in
-;; that position.  If you define a target with a different name,
-;; flymake-for-csharp will conclude that it is not useful for syntax
-;; checking. If you define a target with a different text layout,
-;; flymake-for-csharp won't find it with its naive text search.
-;;
-;; To insure that you use msbuild to do the syntax checking, be sure
-;; that on the `flymake-for-csharp-buildfile-alist' list, a matching
-;; msbuild file appears before a matching makefile.  flymake-for-csharp
-;; will use the first suitable build file (either a makefile or a
-;; msbuild file) that it finds.
-;;
-;; Flymake invokes msbuild with several properties defined on the
-;; command line:
-;;
-;;     SourceFileToCheck - the name of the file to check.  This is a source
-;;                 file with a temporary name, copied from the current
-;;                 state of the buffer.  If you are editing Module.cs, then
-;;                 the value of this property will be  Module_flymake.cs
-;;
-;;     OriginalSourceFile  - the name of the original file that is being
-;;                 checked for syntax.  In the above example, it will be
-;;                 Module.cs
-;;
-;; If the source you are editing consists of small utility programs that
-;; each rely on a single source file, you can use a standard,
-;; boilerplate, build file.  Define it like this:
-;;
-;; <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003";
-;;         DefaultTargets="CompileAll"
-;;         ToolsVersion="3.5"
-;;       >
-;;
-;;  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
-;;
-;;  <!-- specify reference assemblies for all builds in this project -->
-;;  <ItemGroup>
-;;    <Reference Include="mscorlib" />
-;;    <Reference Include="System" />
-;;    <Reference Include="System.Core" />
-;;    <Reference Include="System.Data" />
-;;    <Reference Include="System.Data.Linq" />                   <!-- LINQ -->
-;;    <!--Reference Include="System.ServiceModel" /-->           <!-- WCF -->
-;;    <!--Reference Include="System.ServiceModel.Web" /-->       <!-- WCF -->
-;;    <!--Reference Include="System.Runtime.Serialization" /-->  <!-- WCF -->
-;;  </ItemGroup>
-;;
-;;  <Target Name="CheckSyntax"
-;;          DependsOnTargets="ResolveAssemblyReferences"
-;;        >
-;;    <CSC
-;;       Sources="$(SourceFileToCheck)"
-;;       References="@(ReferencePath)"
-;;       TargetType="module"
-;;       Toolpath="$(MSBuildToolsPath)"
-;;       Nologo="true"
-;;       />
-;;  </Target>
-;;
-;; </Project>
-;;
-;; -ends-
-;;
-;; (This msbuild file will work only with .NET 3.5 and later.)  Name
-;; that build file according to the constraints described above, and put
-;; the name of the file on `flymake-for-csharp-buildfile-alist' .
-;;
-;; If there are additional assemblies you need to reference, add them as
-;; you would normally, by adding an additional <Reference> element under
-;; the <ItemGroup> element. If the assembly is inside the GAC, then use
-;; <Reference Include=""/> and specify the short name of the assembly.
-;; If the assembly is located in the filesystem, specify the path to the
-;; DLL, relative to the local directory. For example, you can specify
-;; c:\ionic\Ionic.Zip.dll if the source module references the DotNetZip
-;; assembly and if that DLL is found in the c:\ionic directory.
-;;
-;; If your projects consist of multiple source files, then you need to
-;; get fancier.  The way flymake works is, it copies the current
-;; contents of the buffer to a temporary source file, then compiles it.
-;; Therefore in the case where you are compiling multiple source files
-;; together, you need to compile all files, *including* the temporary
-;; copy of the file being edited, but *excluding* the actual source file
-;; being edited. This is easily done in msbuild with a
-;; specially-structured Exclude qualifier, referencing the
-;; OriginalSourceFile property. Your msbuild.flymake.xml file should
-;; look something like this:
-;;
-;; <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003";
-;;          DefaultTargets="CompileAll"
-;;          ToolsVersion="3.5"
-;;          >
-;;
-;;   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
-;;
-;;    <PropertyGroup>
-;;       <Optimize>false</Optimize>
-;;       <DebugSymbols>true</DebugSymbols>
-;;       <!-- <OutputPath>.\bin\</OutputPath>  -->
-;;       <OutputPath>.\</OutputPath>
-;;       <OutDir>.\</OutDir>
-;;       <IntermediateOutputPath>.\obj\</IntermediateOutputPath>
-;;    </PropertyGroup>
-;;
-;;   <!-- specify reference assemblies for all builds in this project -->
-;;   <ItemGroup>
-;;     <Reference Include="mscorlib" />
-;;     <Reference Include="System" />
-;;     <Reference Include="System.Core" />
-;;     <Reference Include="System.Data" />
-;;     <Reference Include="System.Data.Linq" />                   <!-- LINQ -->
-;;     <!--Reference Include="System.ServiceModel" /-->           <!-- WCF -->
-;;     <!--Reference Include="System.ServiceModel.Web" /-->       <!-- WCF -->
-;;     <!--Reference Include="System.Runtime.Serialization" /-->  <!-- WCF -->
-;;   </ItemGroup>
-;;
-;;   <!-- This ItemGroup includes every .cs source file in the directory,      
     -->
-;;   <!-- except for the one indicated by OriginalSourceFile.  In flymake, 
that     -->
-;;   <!-- property indicates the currently edited file. So the result is that 
the   -->
-;;   <!-- ItemGroup CSFile will include all files, including the _flymake.cs 
clone, -->
-;;   <!-- but not including the original file.  Which is what we want.         
     -->
-;;   <ItemGroup>
-;;     <CSFile Include="*.cs" Exclude="$(OriginalSourceFile)" />
-;;   </ItemGroup>
-;;
-;;   <!-- Stuff the OriginalSourceFile property into an ItemGroup.             
     -->
-;;   <!-- We do this so we can get at the metadata, which is available only    
     -->
-;;   <!-- through an item within an ItemGroup.  We want the root filename, 
which    -->
-;;   <!-- we use to name the output netmodule.                                 
     -->
-;;   <ItemGroup>
-;;     <ExcludedCSFile Include="$(OriginalSourceFile)" />
-;;   </ItemGroup>
-;;
-;;   <Target Name="CheckSyntax"
-;;           DependsOnTargets="ResolveAssemblyReferences"
-;;           >
-;;     <!-- Run the Visual C# compilation on the specified set of .cs files. 
-->
-;;     <CSC
-;;        Sources="@(CSFile)"
-;;        References="@(ReferencePath)"
-;;        TargetType="module"
-;;        Toolpath="$(MSBuildToolsPath)"
-;;        OutputAssembly="%(ExcludedCSFile.Filename)_flymake.netmodule"
-;;        Nologo="true"
-;;        />
-;;   </Target>
-;;
-;; </Project>
-;;
-;; -ends-
-;;
-;; (The above msbuild file also works only with .NET 3.5.)
-;;
-;; The above assumes that every .cs file in the current directory should be
-;; compiled together.  If this is not the case, then modify the msbuild file
-;; accordingly, to exclude the files as appropriate.  You can also specify
-;; additional references, and so on.
-;;
-
-
-(require 'flymake)
-
-
-
-;;(setq flymake-log-level 3)  ;; insure flymake errors get plopped into the 
*Messages* buffer
-;; -1 = NONE, 0 = ERROR, 1 = WARNING, 2 = INFO, 3 = DEBUG"
-
-
-;; flymake-gui-warnings-enabled
-;; nil = turn off? GUI warnings, eg. when no msbuild.flymake.xml file found
-;; t = turn on? GUI warnings
-(setq flymake-gui-warnings-enabled nil)
-
-
-
-;; New variables for use with flymake-for-csharp
-(defvar flymake-for-csharp-netsdk-location "c:\\netsdk2.0"
-  "Location of .NET SDK, for finding nmake.exe.
-flymake-for-csharp looks for nmake.exe in the bin subdirectory
-of the given directory.  An example value is: c:\\Program
-Files\\Microsoft Visual Studio 8\\SDK\\v2.0 . This variable is
-referenced only if the build-file is an msbuild-compatible
-file. See `flymake-for-csharp-buildfile-alist' for details.")
-
-(defvar flymake-for-csharp-dotnet-location "c:\\.net3.5"
-  "Directory containing MSBuild.exe and csc.exe. Typically, this
-is c:\\Windows\\Microsoft.NET\\Framework\\v3.5 .  This variable
-is referenced if the build-file is an msbuild-compatible file,
-or if using csc. See `flymake-for-csharp-buildfile-alist' for
-details.")
-
-(defvar flymake-for-csharp-grep-pgm  "grep.exe"
-  "The location of the grep program on your system.  This can be
-a bare file if you want flymake-for-csharp to find grep.exe on
-the path. ")
-
-(defvar flymake-for-csharp-buildfile-alist
-  (list "makefile" "makefile.flymake" "flymake.mak" "*.flymake.xml"
-        "*.csproj")
-  "A list of build files that flymake should look for. Wildcards
-are allowed. For each filename in this list, flymake-for-csharp
-will check the existence of the file in the local directory.  If
-the file exists, it will determine if the file has the
-appropriate target, then invoke the associated build tool.  If
-the filename is 'makefile' or begins with 'makefile' or ends in
-.mak, flymake-for-csharp will try to use the file with nmake.  If
-the filename is '*.csproj' or 'msbuild.*' or ends in '.xml',
-flymake will try to use the build file with msbuild.  The build
-file you specify should have the check-syntax target contained
-within it. If none of the build files on the list seem
-appropriate, then flymake-for-csharp will resort to directly
-compiling the current file by itself, using csc.exe.
-" )
-
-
-(defvar flymake-for-csharp-csc-arguments
-  (list "/t:module" "/nologo")
-  "A list of arguments to use with the csc.exe
-compiler, when using flymake-for-csharp with a
-direct csc.exe build for syntax checking purposes.")
-
-
-
-(defvar flymake-for-csharp-most-recent-cmd  nil
-  "The most recent command line used to run flymake
-for the current csharp buffer.
-
-Use this to figure out what flymake-for-csharp decided
-to do, given your setup, variable settings, and the value
-of `flymake-for-csharp-buildfile-alist'.
-
-The value is possily nil, if flymake
-has never been run on the buffer.
-")
-
-
-
-(defun flymake-for-csharp-cleanup ()
-  "Delete the temporary .netmodule file created in syntax checking,
-then call through to flymake-simple-cleanup."
-  (flymake-log 3 "flymake-for-csharp-cleanup")
-  (if flymake-temp-source-file-name
-  (let* ((netmodule-name
-          (concat (file-name-sans-extension flymake-temp-source-file-name)
-                              ".netmodule"))
-         (expanded-netmodule-name (expand-file-name netmodule-name "."))
-         )
-    (if (file-exists-p expanded-netmodule-name)
-        (flymake-safe-delete-file expanded-netmodule-name)
-      )
-    )
-  )
-    (flymake-simple-cleanup)
-
-  )
-
-
-
-(defun flymake-for-csharp-grep-target-in-build-file (target file)
-  "run grep"
-  (interactive)
-  (save-excursion
-    (let ((buf (get-buffer-create "*flymake* csharp-grep-out"))
-          (beg 0))
-      (set-buffer buf)  ;; switch-to-buffer
-      (delete-region (point-min) (point-max))
-      (setq beg (point-min))
-      (goto-char (point-min))
-      (call-process flymake-for-csharp-grep-pgm ;; program
-                    nil        ;; infile - which file to use for input
-                    t          ;; buffer - t means current
-                    nil        ;; display - non-nil means redisplay buf as 
output arrives
-                    "-F"       ;; args - "-F" means treat expression as plain 
text
-                    target     ;;        target - what to search for.  eg, 
"check-syntax"
-                    file       ;;        file - the to search in
-                    "NUL"      ;;        NUL - make sure we print out the 
filename
-                    )
-      (goto-char (point-min))
-      (if (> (point-max) (point-min))
-          (flymake-log 4 "flymake-for-csharp-grep: f(%s) t(%s) output(%s)"
-                       file target
-                       (buffer-substring-no-properties (point-min) (1- 
(point-max))))
-        (flymake-log 4 "flymake-for-csharp-grep f(%s) t(%s): no output" file 
target))
-
-      (re-search-forward target nil t))))
-
-
-
-(defun string-starts-with (s arg)
-  "returns t if string S starts with ARG.  Else nil."
-  (cond ((>= (length s) (length arg))
-         (string-equal (substring s 0 (length arg)) arg))
-        (t nil)))
-
-
-
-(defun flymake-for-csharp-get-csc-arguments ()
-  "gets the args for csc.exe.  You might think this could just be a variable
-reference, but it's packaged as a function to allow advice to override it.
-In particular, the flymake-for-csharp-ext.el package overrides this to
-provide a list of /R arguments, corresponding to the using statements in
-the source file.  That extension ( flymake-for-csharp-ext.el) depends on
-the CSDE package, and not everybody has CSDE installed, or wants it.
-So it remains an extension, and this needs to be a function.
-
-This func also does checking to verify the /t:module is used in the arglist,
-and burps if a different /t argument is found."
-
-  (flymake-log 3 "flymake-for-csharp-get-csc-arguments: entry")
-  (let ((args flymake-for-csharp-csc-arguments)
-        arg
-        (found nil))
-    (flymake-log 3 "flymake-for-csharp-get-csc-arguments: args: %s" args)
-    (while args
-      (setq arg (car args))
-      (cond
-       ((string-equal arg "/t:module") (setq found t))
-       ((string-starts-with arg "/t:")
-        (setq found t)
-        (message "flymake-for-csharp: WARNING /t: option present, and not 
/t:module; fix this.")))
-
-      (setq args (cdr args)))
-    (if found
-        (progn
-          (flymake-log 3 "flymake-for-csharp-get-csc-arguments: return %s" 
flymake-for-csharp-csc-arguments)
-          flymake-for-csharp-csc-arguments)
-
-      (flymake-log 1 "flymake-for-csharp-get-csc-arguments: appending 
/t:module")
-      (setq args
-            (append flymake-for-csharp-csc-arguments (list "/t:module"))))))
-
-
-
-(defun flymake-for-csharp-figure-build ()
-"Figures the build file and type of build to run for flymake.  It
-does this by examining the `flymake-for-csharp-buildfile-alist',
-checking for existence of each file, then checking (best effort)
-for the appropriate flymake target in the buildfile. If none of those
-files exist or if they lack appropriate targets, then it backs off
-to a csc.exe build."
-  (let ((filelist
-         ;; this does wildcard-expansion of the alist, then consolidates
-         ;; to a single list
-         (apply #'append
-                (mapcar '(lambda (a) (file-expand-wildcards a t))
-                        flymake-for-csharp-buildfile-alist)))
-        (build-file nil)
-        (build-type nil))
-
-    (while filelist
-      (setq build-file (car filelist))
-      (flymake-log 4 "flymake-for-csharp-figure-build: file(%s)" build-file)
-      (if (file-exists-p build-file)
-          ;;then
-          (progn
-            (flymake-log 3 "flymake-for-csharp-figure-build: file(%s) exists" 
build-file)
-            (cond
-             ((or (not (null (string-match "makefile" build-file)))
-                  (not (null (string-match ".*\\.mak$" build-file))))
-              (if (flymake-for-csharp-grep-target-in-build-file 
"check-syntax:" build-file)
-                  (setq build-type "nmake"
-                        filelist nil)
-                (flymake-log 3 "flymake-for-csharp-figure-build: file(%s) - no 
suitable target"
-                             build-file)))
-
-             ((or (not (null (string-match "msbuild" build-file)))
-                  (not (null (string-match ".*\\.xml$" build-file)))
-                  (not (null (string-match ".*\\.csproj$" build-file))))
-              (if (flymake-for-csharp-grep-target-in-build-file
-                   "<Target Name=\"CheckSyntax\""  build-file)
-                  (setq build-type "msbuild"
-                        filelist nil)
-                (flymake-log 3 "flymake-for-csharp-figure-build: file(%s) - no 
suitable target"
-                             build-file)))
-
-             (t
-                (flymake-log 3 "flymake-for-csharp-figure-build: file(%s) - 
not a recognized file"
-                             build-file))))
-        ;;else
-        (flymake-log 3 "flymake-for-csharp-figure-build: file(%s) does not 
exist" build-file))
-
-      (if (null build-type)
-          (progn
-            (setq filelist (cdr filelist))
-            (setq build-file nil))))
-
-    (if (null build-type)
-      (setq build-type "csc"))
-
-    (list build-type build-file)))
-
-
-
-
-
-(defun flymake-for-csharp-init ()
-  (flymake-for-csharp-init-impl 'flymake-create-temp-inplace t t  
'flymake-for-csharp-get-flymake-cmdline))
-
-
-(defun flymake-for-csharp-init-impl (create-temp-f use-relative-base-dir 
use-relative-source get-cmdline-f)
-  "Create syntax check command line for a directly checked source file.
-Use CREATE-TEMP-F for creating temp copy."
-  (let* ((args nil)
-        (temp-source-file-name  (flymake-init-create-temp-buffer-copy 
create-temp-f)))
-
-    (setq args (flymake-get-syntax-check-program-args temp-source-file-name 
"."  ;; buildfile-dir
-                                                      use-relative-base-dir 
use-relative-source
-                                                      get-cmdline-f))
-    (flymake-log 3 "flymake-for-csharp-init: %s" (prin1-to-string args))
-    args))
-
-
-;(debug-on-entry 'flymake-for-csharp-init)
-
-
-
-
-;;(defun flymake-get-make-cmdline (source base-dir)
-(defun flymake-for-csharp-get-flymake-cmdline (source base-dir)
-"Gets the cmd line for running a flymake session in a csharp buffer.
- It will invoke one of three programs: csc.exe, msbuild.exe, or nmake.exe,
- depending on the state of the filesystem.  If an appropriate build file,
- suitable for use with either nmake or msbuild, is found on the
- `flymake-for-csharp-buildfile-alist', then the appropriate build tool
- (msbuild or nmake) is invoked on that build file. If no appropriate build
- file is found, then csc.exe is invoked"
-(setq flymake-for-csharp-most-recent-cmd
-  (let* ((build (flymake-for-csharp-figure-build))
-         (flavor (car build)) ;; flavor:  "msbuild" or "nmake" or "csc"
-         (build-file (cadr build))
-        )
-    (cond
-     ((string= flavor "msbuild")
-      (list (concat  flymake-for-csharp-dotnet-location "\\msbuild.exe")
-            (list build-file
-                  ;;(concat base-dir "/" build-file)
-                  "/nologo"
-                  "/t:CheckSyntax"
-                  "/v:quiet"  ;; normal
-                  ;; use file-relative-name to remove the fully-qualified 
directory name
-                  (concat "/property:SourceFileToCheck=" (file-relative-name 
source))
-                  (concat "/property:OriginalSourceFile=" (file-relative-name 
buffer-file-name))
-                  )))
-     ((string= flavor "nmake")
-      (list (concat  flymake-for-csharp-netsdk-location "\\bin\\nmake.exe")
-            (list "/f"
-                  build-file
-                  ;;(concat base-dir "/" build-file)
-                  "/nologo"
-                  "FLYMAKE_SYNTAX_CHECK=1"
-                  (concat "FLYMAKE_CHECK=" source)
-                  (concat "FLYMAKE_ORIGINAL=" (file-relative-name 
buffer-file-name))
-                  "check-syntax")))
-     (t
-      (list (concat  flymake-for-csharp-dotnet-location "\\csc.exe")
-        (append (flymake-for-csharp-get-csc-arguments) (list source))))))))
-
-
-
-
-; This fixup sets flymake to use a different cleanup routine for c# compiles.
-; need to do this only once, not every time csharp-mode is invoked.
-
-(progn
-  (let (elt
-        (csharp-entry nil)
-        (masks flymake-allowed-file-name-masks))
-
-    ;; The "flymake-allowed-file-name-masks" variable stores a filename 
pattern as
-    ;; well as the make-init function, and a cleanup function.  In the case of 
csharp,
-    ;; the setting in flymake.el has the cleanup fn as nil, which means it 
gets the
-    ;; standard cleanup : the *_flymake.cs cloned source file gets deleted.  
But the
-    ;; flymake-for-csharp compiles the .cs file into a module,
-    ;; which also needs to be deleted afterwards.
-    ;;
-
-    ;; Here, we remove the C# entry in the "flymake-allowed-file-name-masks"
-    ;; variable, and replace it with an entry that includes a custom csharp 
cleanup
-    ;; routine.  That cleanup routine deletes the .netmodule file, generated
-    ;; by a successful flymake run.
-
-    ;; I could just setq the "flymake-allowed-file-name-masks" var to the C# 
thing I
-    ;; want, but that would obliterate all the masks for all other languages, 
which
-    ;; would be bad manners.
-    ;;
-    ;; You know, come to think of it, I could just delete the generated 
.netmodule
-    ;; file in the msbuild or makefile.  That might be simpler.
-    ;;
-    ;; But the main point is this ought to be more easily configurable or 
customizable
-    ;; in flymake.el.  And also, flymake ought to do something reasonable for 
csharp builds,
-    ;; rather than completely punt.
-    ;;
-    ;; This fixup is really hacky, relying on the string that is used for 
csharp in
-    ;; flymake.el.  But it will do for now...
-
-    ;; Find the entry
-    (while (consp masks)
-      (setq elt (car masks))
-      (if (string= "\\.cs\\'" (car elt))
-          (setq csharp-entry elt)
-        )
-      (setq masks (cdr masks))
-      )
-
-    ;;  remove the original cleanup item entry ...
-    (if csharp-entry
-        (setq flymake-allowed-file-name-masks
-              (delete csharp-entry flymake-allowed-file-name-masks)))
-
-    ;; Now add a new cleanup item entry, with the custom cleanup method.
-    (setq flymake-allowed-file-name-masks
-          (cons
-           '("\\.cs\\'" flymake-for-csharp-init flymake-for-csharp-cleanup)
-           flymake-allowed-file-name-masks))
-    )
-  )
-
-
-
-
-;; =======================================================
-;;
-;; This section attempts to workaround some anomalous display ebhavior
-;; for tooltips.  It's not strictly necessary, only aesthetic.  The issue is 
that
-;; tooltips can get clipped.  This is the topic of Emacs bug #5908, unfixed
-;; in v23 and present in v22.
-
-(defun cheeso-reverse-string (s)
-  "Reverse a string."
-  (coerce (reverse (loop for b across s
-                         collect b))
-          'string))
-
-(defun cheeso-string-trim (s &rest chars)
-  "Trim any char in string CHARS from either end of string S.
-Often this fn is called with a literal space, as with
-(cheeso-string-trim my-string ?\ ) ."
-  (apply 'cheeso-string-trim-right
-         (apply 'cheeso-string-trim-left s chars)
-         chars))
-
-(defun cheeso-string-trim-left (s &rest chars)
-  "Trim any char in string CHARS from the left of string S."
-  (let ((idx (dotimes (i (length s))
-               (unless (member (elt s i) chars)
-                 (return i)))))
-    (if idx
-        (subseq s idx)
-      "")))
-
-(defun cheeso-string-trim-right (s &rest chars)
-  "Trim any char in string CHARS from the right of string S."
-  (cheeso-reverse-string (apply 'cheeso-string-trim-left 
(cheeso-reverse-string s) chars)))
-
-
-(defun cheeso-reform-string (limit arg)
-  "Reforms a single-line string ARG to a multi-line string with a max
-of LIMIT chars on a line.
-
-This is intended to solve a problem with the display of tooltip text
-in emacs on Win32 - which is that the tooltip is extended to be very very
-long, and the final line is clipped.
-
-The solution is to split the text into multiple lines, and to add a
-trailing newline to trick the tooltip logic into doing the right thing."
-  (let ((orig arg) (modified "") (curline "") word
-        (words (split-string arg " ")))
-    (while words
-      (progn
-        (setq word (car words))
-        (setq words (cdr words))
-        (if (stringp word)
-            (progn
-            (if (> (+ (length curline) (length word) 1) limit)
-                ;; then
-                (progn
-                  (setq modified (concat modified curline "\n"))
-                  (setq curline "")))
-            (setq curline (concat curline " " word)))
-
-            )))
-
-    (setq modified (concat modified curline " \n\n")))
-  )
-
-
-(defadvice tooltip-show (before
-                         flymake-for-csharp-fixup-tooltip
-                         (arg &optional use-echo-area)
-                         activate compile)
-  (progn
-    (if ;;(and (not use-echo-area) (eq major-mode 'csharp-mode))
-        (not use-echo-area)
-        (let ((orig (ad-get-arg 0)))
-          (ad-set-arg 0 (concat " " (cheeso-string-trim (cheeso-reform-string 
74 orig) ?\ )))
-          ))))
-
-;; =======================================================
-
-
-(defadvice flymake-posn-at-point-as-event (before
-                                           flymake-for-csharp-advice-4
-                                           (&optional position window dx dy)
-                                           compile activate)
-  (let ((dx1 (ad-get-arg 2))
-        (dy1 (ad-get-arg 3)))
-    (if (not (null dx1))
-        (setq dx1 (+ dx1 20))
-      (setq dx1 20))
-    (if (not (null dy1))
-        (setq dy1 (+ dy1 14))
-      (setq dy1 14))
-
-    (ad-set-arg 2 dx1)
-    (ad-set-arg 3 dy1)
-
-    )
-  )
-
-
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(provide 'flymake-for-csharp)
-
-;;; end of flymake-for-csharp.el



reply via email to

[Prev in Thread] Current Thread [Next in Thread]