#develop (short for SharpDevelop) is a free IDE for .NET programming languages.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

510 lines
14 KiB

using System;
using System.IO;
using System.Threading;
using System.Collections;
using System.Collections.Generic;
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;
using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Dom;
namespace ICSharpCode.Core
{
public class CaseSensitiveProjectContent : IProjectContent
{
List<IProjectContent> referencedContents = new List<IProjectContent>();
Dictionary<string, IClass> classes = new Dictionary<string, IClass>();
Hashtable namespaces = new Hashtable();
XmlDoc xmlDoc = new XmlDoc();
public XmlDoc XmlDoc {
get {
return xmlDoc;
}
}
public ICollection<IClass> Classes {
get {
return classes.Values;
}
}
public string GetXmlDocumentation(string memberTag)
{
if (xmlDoc.XmlDescription.ContainsKey(memberTag)) {
return xmlDoc.XmlDescription[memberTag];
}
foreach (IProjectContent referencedContent in referencedContents) {
if (referencedContent.XmlDoc.XmlDescription.ContainsKey(memberTag)) {
return referencedContent.XmlDoc.XmlDescription[memberTag];
}
}
return null;
}
static string LookupLocalizedXmlDoc(string fileName)
{
string xmlFileName = Path.ChangeExtension(fileName, ".xml");
string localizedXmlDocFile = FileUtility.Combine(System.IO.Path.GetDirectoryName(fileName), Thread.CurrentThread.CurrentUICulture.TwoLetterISOLanguageName, System.IO.Path.GetFileName(xmlFileName));
if (File.Exists(localizedXmlDocFile)) {
return localizedXmlDocFile;
}
if (File.Exists(xmlFileName)) {
return xmlFileName;
}
return null;
}
public static IProjectContent Create(Assembly assembly)
{
CaseSensitiveProjectContent newProjectContent = new CaseSensitiveProjectContent();
ICompilationUnit assemblyCompilationUnit = new ICSharpCode.SharpDevelop.Dom.NRefactoryResolver.NRefactoryASTConvertVisitor.CompilationUnit(newProjectContent);
foreach (Type type in assembly.GetTypes()) {
if (!type.FullName.StartsWith("<") && type.IsPublic) {
newProjectContent.AddClassToNamespaceList(new ReflectionClass(assemblyCompilationUnit, type, null));
}
}
string fileName = LookupLocalizedXmlDoc(assembly.Location);
// Not found -> look in runtime directory.
if (fileName == null) {
string runtimeDirectory = System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory();
fileName = LookupLocalizedXmlDoc(Path.Combine(runtimeDirectory, Path.GetFileName(assembly.Location)));
}
if (fileName != null) {
newProjectContent.xmlDoc = XmlDoc.Load(fileName);
}
return newProjectContent;
}
public static IProjectContent Create(IProject project)
{
CaseSensitiveProjectContent newProjectContent = new CaseSensitiveProjectContent();
newProjectContent.referencedContents.Add(ProjectContentRegistry.GetMscorlibContent());
foreach (ProjectItem item in project.Items) {
switch (item.ItemType) {
case ItemType.Reference:
IProjectContent referencedContent = ProjectContentRegistry.GetProjectContentForReference(item as ReferenceProjectItem);
if (referencedContent != null) {
newProjectContent.referencedContents.Add(referencedContent);
}
break;
case ItemType.Compile:
ParseInformation parseInfo = ParserService.ParseFile(item.FileName, null, true, false);
newProjectContent.UpdateCompilationUnit(null, parseInfo.BestCompilationUnit as ICompilationUnit, item.FileName, true);
break;
}
}
return newProjectContent;
}
public Hashtable AddClassToNamespaceList(IClass addClass)
{
classes[addClass.FullyQualifiedName] = addClass;
string nSpace = addClass.Namespace;
if (nSpace == null) {
nSpace = String.Empty;
}
string[] path = nSpace.Split('.');
lock (namespaces) {
Hashtable cur = namespaces;
for (int i = 0; i < path.Length; ++i) {
object curPath = cur[path[i]];
if (curPath == null) {
Hashtable hashTable = new Hashtable();
cur[path[i]] = curPath = hashTable;
} else {
if (!(curPath is Hashtable)) {
return null;
}
}
cur = (Hashtable)curPath;
}
string name = addClass.Name == null ? "" : addClass.Name;
cur[name] = addClass;
return cur;
}
}
public void UpdateCompilationUnit(ICompilationUnit oldUnit, ICompilationUnit parserOutput, string fileName, bool updateCommentTags)
{
if (updateCommentTags) {
TaskService.UpdateCommentTags(fileName, parserOutput.TagComments);
}
if (oldUnit != null) {
RemoveClasses(oldUnit);
}
ICompilationUnit cu = (ICompilationUnit)parserOutput;
foreach (IClass c in cu.Classes) {
AddClassToNamespaceList(c);
}
}
void RemoveClasses(ICompilationUnit cu)
{
if (cu != null) {
lock (classes) {
foreach (IClass c in cu.Classes) {
classes.Remove(c.FullyQualifiedName);
}
}
}
}
#region Default Parser Layer dependent functions
public IClass GetClass(string typeName)
{
// Console.WriteLine("GetClass({0}) is known:{1}", typeName, classes.ContainsKey(typeName));
if (classes.ContainsKey(typeName)) {
return classes[typeName];
}
// Search in references:
foreach (IProjectContent content in referencedContents) {
IClass classFromContent = content.GetClass(typeName);
if (classFromContent != null) {
return classFromContent;
}
}
// not found -> maybe nested type -> trying to find class that contains this one.
int lastIndex = typeName.LastIndexOf('.');
if (lastIndex > 0) {
string innerName = typeName.Substring(lastIndex + 1);
string outerName = typeName.Substring(0, lastIndex);
IClass upperClass = GetClass(outerName);
if (upperClass != null && upperClass.InnerClasses != null) {
foreach (IClass c in upperClass.InnerClasses) {
if (c.Name == innerName) {
return c;
}
}
}
}
return null;
}
public string[] GetNamespaceList(string subNameSpace)
{
// Console.WriteLine("GetNamespaceList({0})", subNameSpace);
System.Diagnostics.Debug.Assert(subNameSpace != null);
List<string> namespaceList = new List<string>();
foreach (IProjectContent content in referencedContents) {
string[] referencedNamespaces = content.GetNamespaceList(subNameSpace);
if (referencedNamespaces != null) {
namespaceList.AddRange(referencedNamespaces);
}
}
string[] path = subNameSpace.Split('.');
Hashtable cur = namespaces;
if (subNameSpace.Length > 0) {
for (int i = 0; i < path.Length; ++i) {
if (!(cur[path[i]] is Hashtable)) {
return namespaceList.ToArray();
}
cur = (Hashtable)cur[path[i]];
}
}
foreach (DictionaryEntry entry in cur) {
if (entry.Value is Hashtable && entry.Key.ToString().Length > 0) {
namespaceList.Add(entry.Key.ToString());
}
}
return namespaceList.ToArray();
}
public ArrayList GetNamespaceContents(string subNameSpace)
{
ArrayList namespaceList = new ArrayList();
if (subNameSpace == null) {
return namespaceList;
}
foreach (IProjectContent content in referencedContents) {
ArrayList referencedNamespaceContents = content.GetNamespaceContents(subNameSpace);
namespaceList.AddRange(referencedNamespaceContents.ToArray());
}
string[] path = subNameSpace.Split('.');
Hashtable cur = namespaces;
for (int i = 0; i < path.Length; ++i) {
if (!(cur[path[i]] is Hashtable)) {
foreach (DictionaryEntry entry in cur) {
if (entry.Value is Hashtable) {
namespaceList.Add(entry.Key);
}
}
return namespaceList;
}
cur = (Hashtable)cur[path[i]];
}
foreach (DictionaryEntry entry in cur) {
if (entry.Value is Hashtable) {
namespaceList.Add(entry.Key);
} else {
namespaceList.Add(entry.Value);
}
}
return namespaceList;
}
public bool NamespaceExists(string name)
{
// Console.WriteLine("NamespaceExists({0}) == ", name);
if (name == null) {
return false;
}
foreach (IProjectContent content in referencedContents) {
if (content.NamespaceExists(name)) {
return true;
}
}
string[] path = name.Split('.');
Hashtable cur = namespaces;
for (int i = 0; i < path.Length; ++i) {
if (!(cur[path[i]] is Hashtable)) {
return false;
}
cur = (Hashtable)cur[path[i]];
}
return true;
}
public string SearchNamespace(string name, ICompilationUnit unit, int caretLine, int caretColumn)
{
// Console.WriteLine("SearchNamespace({0})", name);
if (NamespaceExists(name)) {
return name;
}
if (unit == null) {
return null;
}
foreach (IUsing u in unit.Usings) {
if (u != null && (u.Region == null || u.Region.IsInside(caretLine, caretColumn))) {
string nameSpace = u.SearchNamespace(name);
if (nameSpace != null) {
return nameSpace;
}
}
}
return null;
}
public IClass SearchType(string name, IClass curType, int caretLine, int caretColumn)
{
if (curType == null) {
return SearchType(name, null, null, caretLine, caretColumn);
}
return SearchType(name, curType, curType.CompilationUnit, caretLine, caretColumn);
}
public IClass SearchType(string name, IClass curType, ICompilationUnit unit, int caretLine, int caretColumn)
{
// Console.WriteLine("SearchType({0})", name);
if (name == null || name == String.Empty) {
return null;
}
IClass c = GetClass(name);
if (c != null) {
return c;
}
if (unit != null) {
foreach (IUsing u in unit.Usings) {
if (u != null && (u.Region == null || u.Region.IsInside(caretLine, caretColumn))) {
c = u.SearchType(name);
if (c != null) {
return c;
}
}
}
}
if (curType == null) {
return null;
}
string fullname = curType.FullyQualifiedName;
string[] namespaces = fullname.Split('.');
StringBuilder curnamespace = new StringBuilder();
for (int i = 0; i < namespaces.Length; ++i) {
curnamespace.Append(namespaces[i]);
curnamespace.Append('.');
StringBuilder nms=new StringBuilder(curnamespace.ToString());
nms.Append(name);
c = GetClass(nms.ToString());
if (c != null) {
return c;
}
}
//// Alex: try to find in namespaces referenced excluding system ones which were checked already
string[] innamespaces = GetNamespaceList("");
foreach (string ns in innamespaces) {
// if (Array.IndexOf(ParserService.assemblyList,ns)>=0) continue;
ArrayList objs=GetNamespaceContents(ns);
if (objs==null) continue;
foreach (object o in objs) {
if (o is IClass) {
IClass oc=(IClass)o;
// || oc.Name==name
if (oc.FullyQualifiedName == name) {
//Debug.WriteLine(((IClass)o).Name);
/// now we can set completion data
objs.Clear();
objs = null;
return oc;
}
}
}
if (objs == null) {
break;
}
}
innamespaces=null;
//// Alex: end of mod
return null;
}
public ArrayList ListMembers(ArrayList members, IClass curType, IClass callingClass, bool showStatic)
{
// Console.WriteLine("ListMembers()");
DateTime now = DateTime.Now;
// enums must be handled specially, because there are several things defined we don't want to show
// and enum members have neither the modifier nor the modifier public
if (curType.ClassType == ClassType.Enum) {
foreach (IField f in curType.Fields) {
if (f.IsLiteral) {
members.Add(f);
}
}
ListMembers(members, GetClass("System.Enum"), callingClass, showStatic);
return members;
}
bool isClassInInheritanceTree = callingClass.IsTypeInInheritanceTree(curType);
if (showStatic) {
foreach (IClass c in curType.InnerClasses) {
if (c.IsAccessible(callingClass, isClassInInheritanceTree)) {
members.Add(c);
}
}
}
foreach (IProperty p in curType.Properties) {
if (p.MustBeShown(callingClass, showStatic, isClassInInheritanceTree)) {
members.Add(p);
}
}
foreach (IMethod m in curType.Methods) {
if (m.MustBeShown(callingClass, showStatic, isClassInInheritanceTree)) {
members.Add(m);
}
}
foreach (IEvent e in curType.Events) {
if (e.MustBeShown(callingClass, showStatic, isClassInInheritanceTree)) {
members.Add(e);
}
}
foreach (IField f in curType.Fields) {
if (f.MustBeShown(callingClass, showStatic, isClassInInheritanceTree)) {
members.Add(f);
}
}
if (curType.ClassType == ClassType.Interface && !showStatic) {
foreach (string s in curType.BaseTypes) {
IClass baseClass = SearchType(s, curType, curType.Region != null ? curType.Region.BeginLine : -1, curType.Region != null ? curType.Region.BeginColumn : -1);
if (baseClass != null && baseClass.ClassType == ClassType.Interface) {
ListMembers(members, baseClass, callingClass, showStatic);
}
}
} else {
IClass baseClass = curType.BaseClass;
if (baseClass != null) {
ListMembers(members, baseClass, callingClass, showStatic);
}
}
return members;
}
public Position GetPosition(string fullMemberName)
{
string[] name = fullMemberName.Split(new char[] {'.'});
string curName = name[0];
int i = 1;
while (i < name.Length && NamespaceExists(curName)) {
curName += '.' + name[i];
++i;
}
Debug.Assert(i <= name.Length);
IClass curClass = GetClass(curName);
if (curClass == null) {
return new Position(null, -1, -1);
}
ICompilationUnit cu = curClass.CompilationUnit;
while (i < name.Length) {
List<IClass> innerClasses = curClass.InnerClasses;
foreach (IClass c in innerClasses) {
if (c.Name == name[i]) {
curClass = c;
break;
}
}
if (curClass.Name != name[i]) {
break;
}
++i;
}
if (i >= name.Length) {
return new Position(cu, curClass.Region != null ? curClass.Region.BeginLine : -1, curClass.Region != null ? curClass.Region.BeginColumn : -1);
}
IMember member = curClass.SearchMember(name[i]);
if (member == null || member.Region == null) {
return new Position(cu, -1, -1);
}
return new Position(cu, member.Region.BeginLine, member.Region.BeginColumn);
}
#endregion
}
}