public List <Declaration> GetDeclarationsForReference(Reference reference) { var output = new List <Declaration>(); var projectName = reference.Name; var path = reference.FullPath; ITypeLib typeLibrary; // Failure to load might mean that it's a "normal" VBProject that will get parsed by us anyway. LoadTypeLibEx(path, REGKIND.REGKIND_NONE, out typeLibrary); if (typeLibrary == null) { return(output); } var projectQualifiedModuleName = new QualifiedModuleName(projectName, path, projectName); var projectQualifiedMemberName = new QualifiedMemberName(projectQualifiedModuleName, projectName); var projectDeclaration = new ProjectDeclaration(projectQualifiedMemberName, projectName, isBuiltIn: true); output.Add(projectDeclaration); var typeCount = typeLibrary.GetTypeInfoCount(); for (var i = 0; i < typeCount; i++) { ITypeInfo info; try { typeLibrary.GetTypeInfo(i, out info); } catch (NullReferenceException) { return(output); } if (info == null) { continue; } var typeName = GetTypeName(info); var typeDeclarationType = GetDeclarationType(typeLibrary, i); QualifiedModuleName typeQualifiedModuleName; QualifiedMemberName typeQualifiedMemberName; if (typeDeclarationType == DeclarationType.Enumeration || typeDeclarationType == DeclarationType.UserDefinedType) { typeQualifiedModuleName = projectQualifiedModuleName; typeQualifiedMemberName = new QualifiedMemberName(projectQualifiedModuleName, typeName); } else { typeQualifiedModuleName = new QualifiedModuleName(projectName, path, typeName); typeQualifiedMemberName = new QualifiedMemberName(typeQualifiedModuleName, typeName); } IntPtr typeAttributesPointer; info.GetTypeAttr(out typeAttributesPointer); var typeAttributes = (TYPEATTR)Marshal.PtrToStructure(typeAttributesPointer, typeof(TYPEATTR)); var attributes = new Attributes(); if (typeAttributes.wTypeFlags.HasFlag(TYPEFLAGS.TYPEFLAG_FPREDECLID)) { attributes.AddPredeclaredIdTypeAttribute(); } Declaration moduleDeclaration; switch (typeDeclarationType) { case DeclarationType.ProceduralModule: moduleDeclaration = new ProceduralModuleDeclaration(typeQualifiedMemberName, projectDeclaration, typeName, true, new List <IAnnotation>(), attributes); break; case DeclarationType.ClassModule: var module = new ClassModuleDeclaration(typeQualifiedMemberName, projectDeclaration, typeName, true, new List <IAnnotation>(), attributes); var implements = GetImplementedInterfaceNames(typeAttributes, info); foreach (var supertypeName in implements) { module.AddSupertype(supertypeName); } moduleDeclaration = module; break; default: string pseudoModuleName = string.Format("_{0}", typeName); var pseudoParentModule = new ProceduralModuleDeclaration( new QualifiedMemberName(projectQualifiedModuleName, pseudoModuleName), projectDeclaration, pseudoModuleName, true, new List <IAnnotation>(), new Attributes()); // Enums don't define their own type but have a declared type of "Long". if (typeDeclarationType == DeclarationType.Enumeration) { typeName = Tokens.Long; } // UDTs and ENUMs don't seem to have a module parent that's why we add a "fake" module // so that the rest of the application can treat it normally. moduleDeclaration = new Declaration( typeQualifiedMemberName, pseudoParentModule, pseudoParentModule, typeName, null, false, false, Accessibility.Global, typeDeclarationType, null, Selection.Home, false, null, true, null, attributes); break; } ComInformation comInfo; if (_comInformation.TryGetValue(typeAttributes.guid, out comInfo)) { comInfo.TypeQualifiedModuleName = typeQualifiedModuleName; comInfo.ModuleDeclaration = moduleDeclaration; comInfo.TypeDeclarationType = typeDeclarationType; } else { _comInformation.Add(typeAttributes.guid, new ComInformation(typeAttributes, 0, info, typeName, typeQualifiedModuleName, moduleDeclaration, typeDeclarationType)); } info.ReleaseTypeAttr(typeAttributesPointer); output.Add(moduleDeclaration); } foreach (var member in _comInformation.Values) { for (var memberIndex = 0; memberIndex < member.TypeAttributes.cFuncs; memberIndex++) { string[] memberNames; IntPtr memberDescriptorPointer; member.TypeInfo.GetFuncDesc(memberIndex, out memberDescriptorPointer); var memberDescriptor = (FUNCDESC)Marshal.PtrToStructure(memberDescriptorPointer, typeof(FUNCDESC)); var memberDeclaration = CreateMemberDeclaration(memberDescriptor, member.TypeAttributes.typekind, member.TypeInfo, member.ImplTypeFlags, member.TypeQualifiedModuleName, member.ModuleDeclaration, out memberNames); if (memberDeclaration == null) { member.TypeInfo.ReleaseFuncDesc(memberDescriptorPointer); continue; } if (member.ModuleDeclaration.DeclarationType == DeclarationType.ClassModule && memberDeclaration is ICanBeDefaultMember && ((ICanBeDefaultMember)memberDeclaration).IsDefaultMember) { ((ClassModuleDeclaration)member.ModuleDeclaration).DefaultMember = memberDeclaration; } output.Add(memberDeclaration); var parameterCount = memberDescriptor.cParams - (memberDescriptor.invkind.HasFlag(INVOKEKIND.INVOKE_PROPERTYGET) ? 0 : 1); var parameters = new List <ParameterDeclaration>(); for (var paramIndex = 0; paramIndex < parameterCount; paramIndex++) { var parameter = CreateParameterDeclaration(memberNames, paramIndex, memberDescriptor, member.TypeQualifiedModuleName, memberDeclaration, member.TypeInfo); var declaration = memberDeclaration as IDeclarationWithParameter; if (declaration != null) { parameters.Add(parameter); declaration.AddParameter(parameter); } output.Add(parameter); } member.TypeInfo.ReleaseFuncDesc(memberDescriptorPointer); if (parameters.Any() && memberDescriptor.cParamsOpt == -1) { parameters.Last().IsParamArray = true; } } for (var fieldIndex = 0; fieldIndex < member.TypeAttributes.cVars; fieldIndex++) { output.Add(CreateFieldDeclaration(member.TypeInfo, fieldIndex, member.TypeDeclarationType, member.TypeQualifiedModuleName, member.ModuleDeclaration)); } } return(output); }
public List <Declaration> GetDeclarationsForReference(Reference reference) { var output = new List <Declaration>(); var projectName = reference.Name; var path = reference.FullPath; ITypeLib typeLibrary; // Failure to load might mean that it's a "normal" VBProject that will get parsed by us anyway. LoadTypeLibEx(path, REGKIND.REGKIND_NONE, out typeLibrary); if (typeLibrary == null) { return(output); } var projectQualifiedModuleName = new QualifiedModuleName(projectName, path, projectName); var projectQualifiedMemberName = new QualifiedMemberName(projectQualifiedModuleName, projectName); var projectDeclaration = new ProjectDeclaration(projectQualifiedMemberName, projectName, isBuiltIn: true); output.Add(projectDeclaration); var typeCount = typeLibrary.GetTypeInfoCount(); for (var i = 0; i < typeCount; i++) { ITypeInfo info; try { typeLibrary.GetTypeInfo(i, out info); } catch (NullReferenceException) { return(output); } if (info == null) { continue; } var typeName = GetTypeName(info); var typeDeclarationType = GetDeclarationType(typeLibrary, i); QualifiedModuleName typeQualifiedModuleName; QualifiedMemberName typeQualifiedMemberName; if (typeDeclarationType == DeclarationType.Enumeration || typeDeclarationType == DeclarationType.UserDefinedType) { typeQualifiedModuleName = projectQualifiedModuleName; typeQualifiedMemberName = new QualifiedMemberName(projectQualifiedModuleName, typeName); } else { typeQualifiedModuleName = new QualifiedModuleName(projectName, path, typeName); typeQualifiedMemberName = new QualifiedMemberName(typeQualifiedModuleName, typeName); } IntPtr typeAttributesPointer; info.GetTypeAttr(out typeAttributesPointer); var typeAttributes = (TYPEATTR)Marshal.PtrToStructure(typeAttributesPointer, typeof(TYPEATTR)); var attributes = new Attributes(); if (typeAttributes.wTypeFlags.HasFlag(TYPEFLAGS.TYPEFLAG_FPREDECLID)) { attributes.AddPredeclaredIdTypeAttribute(); } if (typeAttributes.wTypeFlags.HasFlag(TYPEFLAGS.TYPEFLAG_FAPPOBJECT)) { attributes.AddGlobalClassAttribute(); } Declaration moduleDeclaration; switch (typeDeclarationType) { case DeclarationType.ProceduralModule: moduleDeclaration = new ProceduralModuleDeclaration(typeQualifiedMemberName, projectDeclaration, typeName, true, new List <IAnnotation>(), attributes); break; case DeclarationType.ClassModule: var module = new ClassModuleDeclaration(typeQualifiedMemberName, projectDeclaration, typeName, true, new List <IAnnotation>(), attributes); var implements = GetImplementedInterfaceNames(typeAttributes, info, module); foreach (var supertypeName in implements) { module.AddSupertype(supertypeName); } moduleDeclaration = module; break; default: string pseudoModuleName = string.Format("_{0}", typeName); var pseudoParentModule = new ProceduralModuleDeclaration( new QualifiedMemberName(projectQualifiedModuleName, pseudoModuleName), projectDeclaration, pseudoModuleName, true, new List <IAnnotation>(), new Attributes()); // Enums don't define their own type but have a declared type of "Long". if (typeDeclarationType == DeclarationType.Enumeration) { typeName = Tokens.Long; } // UDTs and ENUMs don't seem to have a module parent that's why we add a "fake" module // so that the rest of the application can treat it normally. moduleDeclaration = new Declaration( typeQualifiedMemberName, pseudoParentModule, pseudoParentModule, typeName, null, false, false, Accessibility.Global, typeDeclarationType, null, Selection.Home, false, null, true, null, attributes); break; } if (typeAttributes.guid == Guid.Empty) { LoadDeclarationsInModule(output, new ComInformation(typeAttributes, 0, info, typeName, typeQualifiedModuleName, moduleDeclaration, typeDeclarationType)); } else { ComInformation comInfo; if (_comInformation.TryGetValue(typeAttributes.guid, out comInfo)) { comInfo.TypeQualifiedModuleName = typeQualifiedModuleName; comInfo.ModuleDeclaration = moduleDeclaration; comInfo.TypeDeclarationType = typeDeclarationType; } else { _comInformation.Add(typeAttributes.guid, new ComInformation(typeAttributes, 0, info, typeName, typeQualifiedModuleName, moduleDeclaration, typeDeclarationType)); } } info.ReleaseTypeAttr(typeAttributesPointer); output.Add(moduleDeclaration); } foreach (var member in _comInformation.Values) { LoadDeclarationsInModule(output, member); } return(output); }