// Copyright (c) Ivan Bondarev, Stanislav Mikhalkovich (for details please see \doc\copyright.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt) using System; using System.Collections; using System.Collections.Generic; using System.Text; using System.IO; using PascalABCCompiler.SyntaxTree; //using ICSharpCode.SharpDevelop.Dom; using System.Reflection; using PascalABCCompiler; using PascalABCCompiler.TreeConverter; using PascalABCCompiler.TreeRealization; //using SymbolTable; using PascalABCCompiler.PCU; using PascalABCCompiler.Parsers; namespace CodeCompletion { public class IntellisensePCUReader { private string unit_name; private string FileName; private string dir; private FileStream fs; private BinaryReader br; private bool readDebugInfo; private PCUFile pcu_file = new PCUFile(); private SymScope root_scope; private SymScope cur_scope; private int ext_pos; private int start_pos; private Hashtable assemblies = new Hashtable(); private Hashtable members = new Hashtable(); private Hashtable ext_members = new Hashtable(); private static Hashtable unit_cache = new Hashtable(CaseInsensitiveHashCodeProvider.Default, CaseInsensitiveComparer.Default); public IntellisensePCUReader() { } public SymScope GetUnit(string FileName) { try { root_scope = unit_cache[FileName] as SymScope; if (root_scope != null) return root_scope; unit_name = System.IO.Path.GetFileNameWithoutExtension(FileName); this.readDebugInfo = true; this.FileName = FileName; if (!File.Exists(FileName)) return null; dir = System.IO.Path.GetDirectoryName(FileName); fs = new FileStream(FileName, FileMode.Open, FileAccess.Read); br = new BinaryReader(fs); ReadPCUHeader(); root_scope = new InterfaceUnitScope(new SymInfo(unit_name, SymbolKind.Namespace,unit_name),null); unit_cache[FileName] = root_scope; cur_scope = root_scope; AddReferencedAssemblies(); ReadInterfacePart(); fs.Close(); } catch (Exception e) { fs.Close(); return root_scope; } return root_scope; } private static bool ReadPCUHead(PCUFile pcu_file, BinaryReader br) { char[] Header = br.ReadChars(PCUFile.Header.Length); for (int i = 0; i < PCUFile.Header.Length; i++) if (Header[i] != PCUFile.Header[i]) return false; pcu_file.Version = br.ReadInt16(); pcu_file.Revision = br.ReadInt32(); pcu_file.CRC = br.ReadInt64(); pcu_file.UseRtlDll = br.ReadBoolean(); pcu_file.IncludeDebugInfo = br.ReadBoolean(); return true; } private void CloseUnit() { fs.Close(); } private void AddMember(SymScope ss, int offset) { members[offset] = ss; } private void InvalidUnitDetected() { //(ssyy) DarkStar - Ïî÷åìó áû â ýòîì ñëó÷àå ïðîñòî íå ïåðåêîìïèëèðîâàòü ìîäóëü? CloseUnit(); throw new InvalidPCUFile(unit_name); } private void ReadPCUHeader() { if (!ReadPCUHead(pcu_file, br) || PCUFile.SupportedVersion != pcu_file.Version) InvalidUnitDetected(); if(pcu_file.IncludeDebugInfo) pcu_file.SourceFileName = br.ReadString(); else pcu_file.SourceFileName = Path.GetFileNameWithoutExtension(FileName); pcu_file.languageName = br.ReadString(); int num_names = br.ReadInt32(); pcu_file.names = new NameRef[num_names]; for (int i=0; i(); for (int i = 0; i < num_directives; i++) { br.ReadString(); br.ReadString(); ReadDebugInfo(); } int num_imp_entity = br.ReadInt32(); ext_pos = (int)br.BaseStream.Position; pcu_file.imp_entitles = new ImportedEntity[num_imp_entity]; br.BaseStream.Seek(num_imp_entity*ImportedEntity.GetClassSize(),SeekOrigin.Current); pcu_file.interface_synonyms_offset = br.ReadInt32(); pcu_file.implementation_synonyms_offset = br.ReadInt32(); br.ReadInt32(); br.ReadInt32(); //ivan int num_net_entities = br.ReadInt32(); pcu_file.dotnet_names = new DotNetNameRef[num_net_entities]; for (int i = 0; i < num_net_entities; i++) { DotNetNameRef dnnr = new DotNetNameRef(); dnnr.kind = (DotNetKind)br.ReadByte(); dnnr.name = br.ReadString(); dnnr.addit = new DotAdditInfo[br.ReadInt32()]; for (int j = 0; j < dnnr.addit.Length; j++) { dnnr.addit[j] = new DotAdditInfo(); dnnr.addit[j].offset = br.ReadInt32(); } pcu_file.dotnet_names[i] = dnnr; } start_pos = (int)br.BaseStream.Position; } private void ReadInterfacePart() { for (int i=0; i interfaces = new List(); for (int i = 0; i < interf_count; i++) { interfaces.Add(GetTypeReference()); } //\ssyy object low_val=null; object upper_val=null; PascalABCCompiler.SemanticTree.type_access_level tal = (PascalABCCompiler.SemanticTree.type_access_level)br.ReadByte(); PascalABCCompiler.SemanticTree.type_special_kind tsk = (PascalABCCompiler.SemanticTree.type_special_kind)br.ReadByte(); bool is_sealed = br.ReadBoolean(); bool is_abstract = br.ReadBoolean(); if (tsk == PascalABCCompiler.SemanticTree.type_special_kind.diap_type) { low_val = CreateExpression(); upper_val = CreateExpression(); } TypeScope element_type = null; if (CanReadObject()) element_type = GetTypeReference(); switch (tsk) { case PascalABCCompiler.SemanticTree.type_special_kind.none_kind : ctn = new TypeScope(SymbolKind.Class,cur_scope,base_type); break; case PascalABCCompiler.SemanticTree.type_special_kind.record : ctn = new TypeScope(SymbolKind.Struct,cur_scope,base_type); break; case PascalABCCompiler.SemanticTree.type_special_kind.array_wrapper : ctn = new ArrayScope(); break; case PascalABCCompiler.SemanticTree.type_special_kind.enum_kind : ctn = new EnumScope(SymbolKind.Enum,cur_scope,base_type); break; case PascalABCCompiler.SemanticTree.type_special_kind.set_type : ctn = new SetScope(element_type); break; case PascalABCCompiler.SemanticTree.type_special_kind.array_kind : if (!in_scope) ctn = new ArrayScope(); else return null; break; case PascalABCCompiler.SemanticTree.type_special_kind.diap_type : ctn = new DiapasonScope(low_val,upper_val);break; case PascalABCCompiler.SemanticTree.type_special_kind.typed_file : ctn = new FileScope(element_type,null);break; case PascalABCCompiler.SemanticTree.type_special_kind.binary_file : ctn = new FileScope(null,null);break; } ctn.declaringUnit = root_scope; ctn.si.name = name; ctn.is_abstract = is_abstract; ctn.is_final = is_sealed; AddMember(ctn, offset); ctn.elementType = element_type; br.ReadInt32(); br.ReadInt32();//attributes //common_namespace_node ns = cun.namespaces[0]; byte flag = br.ReadByte(); int def_prop_off=0; if (flag == 1) { def_prop_off = br.ReadInt32(); } ReadDebugInfo(); ctn.si.description = ctn.GetDescription(); //ñîçäàåì scope äëÿ êëàññà //ctn = new wrapped_common_type_node(this, base_type, name, tal, ns, scope, loc, offset); //members[offset] = ctn; //AddMember(ctn, offset); RestoreAllMembers(ctn); return ctn; } public SymScope CreateInterfaceInClassMember(string name, int offset) { SymScope dn = members[offset] as SymScope; if (dn != null) return dn; int tmp = (int)br.BaseStream.Position; br.BaseStream.Seek(start_pos + offset, SeekOrigin.Begin); semantic_node_type snt = (semantic_node_type)br.ReadByte(); switch (snt) { case semantic_node_type.class_field: dn = CreateInterfaceClassField(name, offset); break; case semantic_node_type.common_property_node: dn = CreateInterfaceProperty(name, offset); break; case semantic_node_type.common_method_node: dn = CreateInterfaceMethod(name, offset); break; //case semantic_node_type.class_constant_definition: // dn = CreateInterfaceClassConstantDefinition(name, offset); break; } br.BaseStream.Seek(tmp, SeekOrigin.Begin); //ProcessWaitedToRestoreFields(); return dn; } private ElementScope CreateInterfaceClassField(string name, int offset) { ElementScope field = members[offset] as ElementScope; if (field != null) return field; int name_off = br.ReadInt32(); TypeScope type = GetTypeReference(); field = new ElementScope(new SymInfo(name, SymbolKind.Field,name),type,cur_scope); field.declaringUnit = root_scope; AddMember(field, offset); object initv = null; if (CanReadObject()) initv = CreateExpression(); br.ReadInt32(); PascalABCCompiler.SemanticTree.field_access_level fal = (PascalABCCompiler.SemanticTree.field_access_level)br.ReadByte(); PascalABCCompiler.SemanticTree.polymorphic_state ps = (PascalABCCompiler.SemanticTree.polymorphic_state)br.ReadByte(); switch (fal) { case PascalABCCompiler.SemanticTree.field_access_level.fal_internal : field.acc_mod = access_modifer.internal_modifer; break; case PascalABCCompiler.SemanticTree.field_access_level.fal_private : field.acc_mod = access_modifer.private_modifer; return null; case PascalABCCompiler.SemanticTree.field_access_level.fal_protected : field.acc_mod = access_modifer.protected_modifer; break; case PascalABCCompiler.SemanticTree.field_access_level.fal_public : field.acc_mod = access_modifer.public_modifer; break; } switch (ps) { case PascalABCCompiler.SemanticTree.polymorphic_state.ps_static : field.is_static = true; break; case PascalABCCompiler.SemanticTree.polymorphic_state.ps_virtual : field.is_virtual = true; break; } //field = new class_field(name,type,cont,ps,fal,loc); field.cnst_val = initv; //members[offset] = field; AddMember(field, offset); return field; } private ElementScope CreateInterfaceProperty(string name, int offset) { ElementScope prop = members[offset] as ElementScope; if (prop != null) return prop; int name_ref = br.ReadInt32(); TypeScope type = GetTypeReference(); if (br.ReadByte() == 1) br.ReadInt32(); if (br.ReadByte() == 1) br.ReadInt32(); int num = br.ReadInt32(); List prms = new List(); for (int i = 0; i < num; i++) prms.Add(GetParameter(null)); br.ReadInt32(); PascalABCCompiler.SemanticTree.field_access_level fal = (PascalABCCompiler.SemanticTree.field_access_level)br.ReadByte(); PascalABCCompiler.SemanticTree.polymorphic_state ps = (PascalABCCompiler.SemanticTree.polymorphic_state)br.ReadByte(); //ReadDebugInfo(); prop = new ElementScope(new SymInfo(name, SymbolKind.Property,name),type,cur_scope); prop.declaringUnit = root_scope; switch (fal) { case PascalABCCompiler.SemanticTree.field_access_level.fal_internal : prop.acc_mod = access_modifer.internal_modifer; break; case PascalABCCompiler.SemanticTree.field_access_level.fal_private : prop.acc_mod = access_modifer.private_modifer; return null; case PascalABCCompiler.SemanticTree.field_access_level.fal_protected : prop.acc_mod = access_modifer.protected_modifer; break; case PascalABCCompiler.SemanticTree.field_access_level.fal_public : prop.acc_mod = access_modifer.public_modifer; break; } switch (ps) { case PascalABCCompiler.SemanticTree.polymorphic_state.ps_static : prop.is_static = true; break; case PascalABCCompiler.SemanticTree.polymorphic_state.ps_virtual : prop.is_virtual = true; break; } //members[offset] = prop; AddMember(prop, offset); return prop; } private ProcScope CreateInterfaceMethod(string name, int offset) { ProcScope cmn = members[offset] as ProcScope; if (cmn != null) return cmn; cmn = new ProcScope(name,cur_scope); cmn.declaringUnit = root_scope; //members[offset] = cmn; AddMember(cmn, offset); int name_ref = br.ReadInt32(); br.ReadByte(); br.ReadByte(); bool is_generic = br.ReadBoolean(); if (is_generic) { throw new NotSupportedException(); } //ssyy //\ssyy if (br.ReadByte() == 1) //return_value_type { cmn.return_type = GetTypeReference(); if (br.ReadByte() == 1) { GetLocalVariable(cmn); } } int num_par = br.ReadInt32(); for (int i = 0; i < num_par; i++) cmn.parameters.Add(GetParameter(cmn)); br.ReadInt32(); br.ReadInt32(); cmn.is_constructor = br.ReadBoolean(); cmn.is_forward = br.ReadBoolean(); br.ReadBoolean(); PascalABCCompiler.SemanticTree.field_access_level fal = (PascalABCCompiler.SemanticTree.field_access_level)br.ReadByte(); PascalABCCompiler.SemanticTree.polymorphic_state ps = (PascalABCCompiler.SemanticTree.polymorphic_state)br.ReadByte(); switch (fal) { case PascalABCCompiler.SemanticTree.field_access_level.fal_internal : cmn.acc_mod = access_modifer.internal_modifer; break; case PascalABCCompiler.SemanticTree.field_access_level.fal_private : cmn.acc_mod = access_modifer.private_modifer; return null; case PascalABCCompiler.SemanticTree.field_access_level.fal_protected : cmn.acc_mod = access_modifer.protected_modifer; break; case PascalABCCompiler.SemanticTree.field_access_level.fal_public : cmn.acc_mod = access_modifer.public_modifer; break; } switch (ps) { case PascalABCCompiler.SemanticTree.polymorphic_state.ps_static : cmn.is_static = true; break; case PascalABCCompiler.SemanticTree.polymorphic_state.ps_virtual : cmn.is_virtual = true; break; } br.ReadInt32(); br.ReadInt32(); cmn.is_override = br.ReadBoolean() == true; cmn.Complete(); return cmn; } private void RestoreAllMembers(TypeScope scope) { int num = br.ReadInt32(); Hashtable ht = new Hashtable(); for (int i = 0; i < num; i++) { string name = br.ReadString(); int offset = br.ReadInt32(); SymScope tmp = cur_scope; cur_scope = scope; SymScope ss = CreateInterfaceInClassMember(name,offset); br.ReadByte(); br.ReadByte(); if (ht.ContainsKey(name) && ss is ProcScope) { (ht[name] as ProcScope).nextProc = ss as ProcScope; ht[name] = ss; } else if (ss is ProcScope) { ht[name] = ss; } cur_scope = tmp; if (ss != null) scope.AddName(name,ss); } } private ProcScope CreateInterfaceNamespaceFunction(string name, int offset) { //Console.WriteLine(name); ProcScope cnfn = new ProcScope(name,cur_scope); cnfn.declaringUnit = root_scope; if (CanReadObject()) br.ReadInt32(); br.ReadBoolean();//ïðîïóñêàåì ôëàã - èíòåðôåéñíîñòè br.ReadInt32();//name index bool is_generic = br.ReadBoolean(); if (is_generic) { throw new NotSupportedException(); } if (br.ReadByte() == 1) { cnfn.return_type = GetTypeReference(); GetLocalVariable(cnfn); } int num_par = br.ReadInt32(); for (int i=0; i 0) return t.MakeGenericType(template_types); return t; } private void AddReferencedAssemblies() { for (int i=0; i