📄 defaultparserservice.cs
字号:
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Mike Krueger" email="mike@icsharpcode.net"/>
// <version value="$version"/>
// </file>
using System;
using System.IO;
using System.Threading;
using System.Collections;
using System.Collections.Utility;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters;
using System.Runtime.Serialization.Formatters.Binary;
using System.Security;
using System.Security.Permissions;
using System.Security.Policy;
using System.Xml;
using System.Text;
using ICSharpCode.Core.Properties;
using ICSharpCode.Core.Services;
using ICSharpCode.SharpDevelop.Services;
using ICSharpCode.Core.AddIns;
using ICSharpCode.SharpDevelop.Internal.Project;
using ICSharpCode.SharpDevelop.Gui;
using SharpDevelop.Internal.Parser;
namespace ICSharpCode.SharpDevelop.Services
{
public class DefaultParserService : AbstractService, IParserService
{
Hashtable classes = new Hashtable();
Hashtable caseInsensitiveClasses = new Hashtable();
// used to map 'real' namespace hashtable inside case insensitive hashtable
const string CaseInsensitiveKey = "__CASE_INSENSITIVE_HASH";
Hashtable namespaces = new Hashtable();
Hashtable caseInsensitiveNamespaces = new Hashtable();
Hashtable parsings = new Hashtable();
ParseInformation addedParseInformation = new ParseInformation();
ParseInformation removedParseInformation = new ParseInformation();
/// <remarks>
/// The keys are the assemblies loaded. This hash table ensures that no
/// assembly is loaded twice. I know that strong naming might be better but
/// the use case isn't there. No one references 2 differnt files if he references
/// the same assembly.
/// </remarks>
Hashtable loadedAssemblies = new Hashtable();
ClassProxyCollection classProxies = new ClassProxyCollection();
IParser[] parser;
readonly static string[] assemblyList = {
"Microsoft.VisualBasic",
"Microsoft.JScript",
"mscorlib",
"System.Data",
"System.Design",
"System.DirectoryServices",
"System.Drawing.Design",
"System.Drawing",
"System.EnterpriseServices",
"System.Management",
"System.Messaging",
"System.Runtime.Remoting",
"System.Runtime.Serialization.Formatters.Soap",
"System.Security",
"System.ServiceProcess",
"System.Web.Services",
"System.Web",
"System.Windows.Forms",
"System",
"System.XML"
};
public DefaultParserService()
{
addedParseInformation.DirtyCompilationUnit = new DummyCompilationUnit();
removedParseInformation.DirtyCompilationUnit = new DummyCompilationUnit();
}
public static string[] AssemblyList {
get {
return assemblyList;
}
}
/// <remarks>
/// The initialize method writes the location of the code completion proxy
/// file to this string.
/// </remarks>
string codeCompletionProxyFile;
string codeCompletionMainFile;
class ClasstableEntry
{
IClass myClass;
ICompilationUnit myCompilationUnit;
string myFileName;
public IClass Class {
get {
return myClass;
}
}
public ICompilationUnit CompilationUnit {
get {
return myCompilationUnit;
}
}
public string FileName {
get {
return myFileName;
}
}
public ClasstableEntry(string fileName, ICompilationUnit compilationUnit, IClass c)
{
this.myCompilationUnit = compilationUnit;
this.myFileName = fileName;
this.myClass = c;
}
}
public void GenerateCodeCompletionDatabase(string createPath, IProgressMonitor progressMonitor)
{
SetCodeCompletionFileLocation(createPath);
// write all classes and proxies to the disc
BinaryWriter classWriter = new BinaryWriter(new BufferedStream(new FileStream(codeCompletionMainFile, FileMode.Create, FileAccess.Write, FileShare.None)));
BinaryWriter proxyWriter = new BinaryWriter(new BufferedStream(new FileStream(codeCompletionProxyFile, FileMode.Create, FileAccess.Write, FileShare.None)));
if (progressMonitor != null) {
progressMonitor.BeginTask("generate code completion database", assemblyList.Length);
}
// convert all assemblies
for (int i = 0; i < assemblyList.Length; ++i) {
try {
FileUtilityService fileUtilityService = (FileUtilityService)ServiceManager.Services.GetService(typeof(FileUtilityService));
string path = fileUtilityService.GetDirectoryNameWithSeparator(System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory());
AssemblyInformation frameworkAssemblyInformation = new AssemblyInformation();
frameworkAssemblyInformation.Load(String.Concat(path, assemblyList[i], ".dll"), false);
// create all class proxies
foreach (IClass newClass in frameworkAssemblyInformation.Classes) {
ClassProxy newProxy = new ClassProxy(newClass);
classProxies.Add(newProxy);
AddClassToNamespaceList(newProxy);
PersistentClass pc = new PersistentClass(classProxies, newClass);
newProxy.Offset = (uint)classWriter.BaseStream.Position;
newProxy.WriteTo(proxyWriter);
pc.WriteTo(classWriter);
}
if (progressMonitor != null) {
progressMonitor.Worked(i);
}
} catch (Exception) {
}
}
classWriter.Close();
proxyWriter.Close();
if (progressMonitor != null) {
progressMonitor.Done();
}
}
void SetCodeCompletionFileLocation(string path)
{
FileUtilityService fileUtilityService = (FileUtilityService)ServiceManager.Services.GetService(typeof(FileUtilityService));
string codeCompletionTemp = fileUtilityService.GetDirectoryNameWithSeparator(path);
codeCompletionProxyFile = codeCompletionTemp + "CodeCompletionProxyDataV02.bin";
codeCompletionMainFile = codeCompletionTemp + "CodeCompletionMainDataV02.bin";
}
void SetDefaultCompletionFileLocation()
{
PropertyService propertyService = (PropertyService)ServiceManager.Services.GetService(typeof(PropertyService));
SetCodeCompletionFileLocation(propertyService.GetProperty("SharpDevelop.CodeCompletion.DataDirectory", String.Empty).ToString());
}
public void LoadProxyDataFile()
{
if (!File.Exists(codeCompletionProxyFile)) {
return;
}
BinaryReader reader = new BinaryReader(new BufferedStream(new FileStream(codeCompletionProxyFile, FileMode.Open, FileAccess.Read, FileShare.Read)));
while (true) {
try {
ClassProxy newProxy = new ClassProxy(reader);
classProxies.Add(newProxy);
AddClassToNamespaceList(newProxy);
} catch (Exception) {
break;
}
}
reader.Close();
}
void LoadThread()
{
SetDefaultCompletionFileLocation();
BinaryFormatter formatter = new BinaryFormatter();
if (File.Exists(codeCompletionProxyFile)) {
LoadProxyDataFile();
}
}
public override void InitializeService()
{
parser = (IParser[])(AddInTreeSingleton.AddInTree.GetTreeNode("/Workspace/Parser").BuildChildItems(this)).ToArray(typeof(IParser));
Thread myThread = new Thread(new ThreadStart(LoadThread));
myThread.IsBackground = true;
myThread.Priority = ThreadPriority.Lowest;
myThread.Start();
IProjectService projectService = (IProjectService)ICSharpCode.Core.Services.ServiceManager.Services.GetService(typeof(IProjectService));
projectService.CombineOpened += new CombineEventHandler(OpenCombine);
}
public void AddReferenceToCompletionLookup(IProject project, ProjectReference reference)
{
if (reference.ReferenceType == ReferenceType.Project) {
IProjectService projectService = (IProjectService)ICSharpCode.Core.Services.ServiceManager.Services.GetService(typeof(IProjectService));
IProject refProject = projectService.GetProject(reference.Reference);
// don't load project assemblies when a parser for them exists
if (refProject == null)
return;
foreach (IParser possibleParser in parser) {
if (possibleParser.CanParse(refProject))
return;
}
}
string fileName = reference.GetReferencedFileName(project);
if (fileName == null || fileName.Length == 0) {
return;
}
foreach (string assemblyName in assemblyList) {
if (Path.GetFileNameWithoutExtension(fileName).ToUpper() == assemblyName.ToUpper()) {
return;
}
}
// // HACK : Don't load references for non C# projects
// if (project.ProjectType != "C#") {
// return;
// }
if (File.Exists(fileName)) {
try {
AssemblyLoader assemblyLoader = new AssemblyLoader(this, fileName);
assemblyLoader.NonLocking = reference.ReferenceType != ReferenceType.Gac;
Thread t = new Thread(new ThreadStart(assemblyLoader.LoadAssemblyParseInformations));
t.IsBackground = true;
t.Start();
} catch (Exception e) { Console.WriteLine(e); }
}
}
class AssemblyLoader
{
DefaultParserService parserService;
string assemblyFileName;
bool nonLocking = false;
public bool NonLocking {
get {
return nonLocking;
}
set {
nonLocking = value;
}
}
public AssemblyLoader(DefaultParserService parserService, string assemblyFileName)
{
this.parserService = parserService;
this.assemblyFileName = assemblyFileName;
}
public void LoadAssemblyParseInformations()
{
if (parserService.loadedAssemblies[assemblyFileName] != null) {
return;
}
parserService.loadedAssemblies[assemblyFileName] = true;
//Console.WriteLine("Before: " + Environment.WorkingSet / (1024 * 1024) + " -- " + assemblyFileName);
try {
AssemblyInformation assemblyInformation = new AssemblyInformation();
assemblyInformation.Load(assemblyFileName, nonLocking);
foreach (IClass newClass in assemblyInformation.Classes) {
Console.WriteLine(newClass);
parserService.AddClassToNamespaceList(newClass);
lock (parserService.classes) {
parserService.caseInsensitiveClasses[newClass.FullyQualifiedName.ToLower()] = parserService.classes[newClass.FullyQualifiedName] = new ClasstableEntry(null, null, newClass);
}
}
} catch (Exception) {
}
//Console.WriteLine("After: " + Environment.WorkingSet / (1024 * 1024) + " -- " + assemblyFileName);
}
}
public virtual void OpenCombine(object sender, CombineEventArgs e)
{
ArrayList projects = Combine.GetAllProjects(e.Combine);
foreach (ProjectCombineEntry entry in projects) {
foreach (ProjectReference r in entry.Project.ProjectReferences) {
AddReferenceToCompletionLookup(entry.Project, r);
}
}
}
public void StartParserThread()
{
Thread parserThread = new Thread(new ThreadStart(ParserUpdateThread));
parserThread.IsBackground = true;
parserThread.Start();
}
public override void UnloadService()
{
doneParserThread = true;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -