Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cache user COM projects (infrastructure) #4535

Merged
merged 28 commits into from Jun 2, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
8155734
Add a LockedProjects to the IProjectsProvider
MDoerner Nov 13, 2018
5da2a42
Add IUserComProjectRepository and implementation
MDoerner Nov 15, 2018
32aaad0
Add safety around compilation argument changes between parses
MDoerner Nov 19, 2018
9829315
Update ComReferencesSynchronizerBase for locked projects
MDoerner Nov 20, 2018
9fa2b15
Add ProjectsToResolveFromComProjectSelector
MDoerner Nov 20, 2018
7d93546
Wire up the ProjectsToBeResolvedFromComProjectSelector
MDoerner Nov 20, 2018
95c60d8
Exract loading declarations from ComProject
MDoerner Nov 21, 2018
2abe7fc
Introduce UserComProjectSynchronizer
MDoerner Nov 21, 2018
0bfa3b0
Uncomment accidentally commented out code in UserProjectsRepository
MDoerner Nov 21, 2018
323e835
Merge branch 'next' into CacheUserComProjects
MDoerner Nov 21, 2018
138b997
First adaptions of the ComProject to VBE typeLibs
MDoerner Nov 22, 2018
d53d42e
Fix ComModule for VBA standard modules
MDoerner Nov 23, 2018
bd2589b
Fix bug in ComInterface
MDoerner Nov 24, 2018
69361fc
Merge branch 'next' into CacheUserComProjects
MDoerner Nov 28, 2018
a5b227b
Merge branch 'next' into CacheUserComProjects
MDoerner Dec 3, 2018
c426d1b
Add runtime logging to UserProjectsRepository and UserComProjectSynch…
MDoerner Dec 4, 2018
6be22c5
Merge branch 'next' into CacheUserComProjects
MDoerner Dec 4, 2018
e0d7df7
Merge branch 'next' into CacheUserComProjects
MDoerner Dec 10, 2018
0bc004e
Prevent null exceptions due to null typelib being returned by explici…
bclothier Dec 22, 2018
254961a
Merge pull request #3 from bclothier/CacheUserComProjects
MDoerner Dec 30, 2018
e5029be
Merge branch 'next' into CacheUserComProjects
MDoerner Jan 3, 2019
7687755
Merge branch 'next' into CacheUserComProjects
MDoerner Mar 31, 2019
b57c05a
Merge branch 'next' into CacheUserComProjects
MDoerner May 11, 2019
034e80c
Only load and process user com projects if LOAD_USER_COM_PROJECTS is set
MDoerner May 11, 2019
0eb4f71
Make minor refactoring to address comments to PR #4535
MDoerner May 11, 2019
38dab3d
Refactor further to address comments to PR #4535 by Vogel612
MDoerner May 12, 2019
61ba7dd
Merge branch 'next' into CacheUserComProjects
MDoerner May 12, 2019
6a23b64
Merge branch 'next' into CacheUserComProjects
MDoerner May 31, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 10 additions & 3 deletions Rubberduck.API/VBA/Parser.cs
Expand Up @@ -94,13 +94,15 @@ internal Parser(object vbe) : this()
_vbeEvents = VBEEvents.Initialize(_vbe);
var declarationFinderFactory = new ConcurrentlyConstructedDeclarationFinderFactory();
var projectRepository = new ProjectsRepository(_vbe);
var projectsToBeLoadedFromComSelector = new ProjectsToResolveFromComProjectsSelector(projectRepository);
_state = new RubberduckParserState(_vbe, projectRepository, declarationFinderFactory, _vbeEvents);
_state.StateChanged += _state_StateChanged;
var vbeVersion = double.Parse(_vbe.Version, CultureInfo.InvariantCulture);
var predefinedCompilationConstants = new VBAPredefinedCompilationConstants(vbeVersion);
var typeLibProvider = new TypeLibWrapperProvider(projectRepository);
var compilationArgumentsProvider = new CompilationArgumentsProvider(typeLibProvider, _dispatcher, predefinedCompilationConstants);
var compilationsArgumentsCache = new CompilationArgumentsCache(compilationArgumentsProvider);
var userProjectsRepository = new UserProjectRepository(typeLibProvider, _dispatcher, projectRepository);
var preprocessorErrorListenerFactory = new PreprocessingParseErrorListenerFactory();
var preprocessorParser = new VBAPreprocessorParser(preprocessorErrorListenerFactory, preprocessorErrorListenerFactory);
var preprocessor = new VBAPreprocessor(preprocessorParser, compilationsArgumentsCache);
Expand All @@ -114,8 +116,10 @@ internal Parser(object vbe) : this()
var referenceRemover = new ReferenceRemover(_state, moduleToModuleReferenceManager);
var supertypeClearer = new SupertypeClearer(_state);
var comLibraryProvider = new ComLibraryProvider();
var referencedDeclarationsCollector = new LibraryReferencedDeclarationsCollector(comLibraryProvider);
var declarationsFromComProjectLoader = new DeclarationsFromComProjectLoader();
var referencedDeclarationsCollector = new LibraryReferencedDeclarationsCollector(declarationsFromComProjectLoader, comLibraryProvider);
var comSynchronizer = new COMReferenceSynchronizer(_state, parserStateManager, projectRepository, referencedDeclarationsCollector);
var userComProjectSynchronizer = new UserComProjectSynchronizer(_state, declarationsFromComProjectLoader, userProjectsRepository, projectsToBeLoadedFromComSelector);
var builtInDeclarationLoader = new BuiltInDeclarationLoader(
_state,
new List<ICustomDeclarationLoader>
Expand Down Expand Up @@ -154,14 +158,17 @@ internal Parser(object vbe) : this()
builtInDeclarationLoader,
parseRunner,
declarationResolveRunner,
referenceResolveRunner
referenceResolveRunner,
userComProjectSynchronizer
);
var parsingCacheService = new ParsingCacheService(
_state,
moduleToModuleReferenceManager,
referenceRemover,
supertypeClearer,
compilationsArgumentsCache
compilationsArgumentsCache,
userProjectsRepository,
projectsToBeLoadedFromComSelector
);

_parser = new SynchronousParseCoordinator(
Expand Down
12 changes: 12 additions & 0 deletions Rubberduck.Main/Root/RubberduckIoCInstaller.cs
Expand Up @@ -924,6 +924,18 @@ private void RegisterParsingEngine(IWindsorContainer container)
container.Register(Component.For<ITypeLibWrapperProvider>()
.ImplementedBy<TypeLibWrapperProvider>()
.LifestyleSingleton());
container.Register(Component.For<IUserComProjectRepository, IUserComProjectProvider>()
.ImplementedBy<UserProjectRepository>()
.LifestyleSingleton());
container.Register(Component.For<IDeclarationsFromComProjectLoader>()
.ImplementedBy<DeclarationsFromComProjectLoader>()
.LifestyleSingleton());
container.Register(Component.For<IUserComProjectSynchronizer>()
.ImplementedBy<UserComProjectSynchronizer>()
.LifestyleSingleton());
container.Register(Component.For<IProjectsToResolveFromComProjectSelector>()
.ImplementedBy<ProjectsToResolveFromComProjectsSelector>()
.LifestyleSingleton());
}

private void RegisterTypeLibApi(IWindsorContainer container)
Expand Down
9 changes: 5 additions & 4 deletions Rubberduck.Parsing/ComReflection/ComModule.cs
Expand Up @@ -34,15 +34,14 @@ public class ComModule : ComType, IComTypeWithMembers, IComTypeWithFields

public ComModule(IComBase parent, ITypeLib typeLib, ITypeInfo info, TYPEATTR attrib, int index) : base(parent, typeLib, attrib, index)
{
Debug.Assert(attrib.cFuncs >= 0 && attrib.cVars >= 0);
bclothier marked this conversation as resolved.
Show resolved Hide resolved
Type = DeclarationType.ProceduralModule;
if (attrib.cFuncs > 0)
{
Debug.Assert(attrib.cVars == 0);
GetComMembers(info, attrib);
}
else
if (attrib.cVars > 0)
{
Debug.Assert(attrib.cVars > 0);
GetComFields(info, attrib);
}
}
Expand All @@ -59,7 +58,9 @@ private void GetComFields(ITypeInfo info, TYPEATTR attrib)
info.GetNames(desc.memid, names, names.Length, out int length);
Debug.Assert(length == 1);

_fields.Add(new ComField(this, info, names[0], desc, index, DeclarationType.Constant));
var type = desc.desc.lpvarValue == IntPtr.Zero ? DeclarationType.Variable : DeclarationType.Constant;
retailcoder marked this conversation as resolved.
Show resolved Hide resolved

_fields.Add(new ComField(this, info, names[0], desc, index, type));
}
}
}
Expand Down
26 changes: 15 additions & 11 deletions Rubberduck.Parsing/ComReflection/ComProject.cs
Expand Up @@ -6,9 +6,10 @@
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Runtime.Serialization;
using Rubberduck.VBEditor.ComManagement.TypeLibs;
using Rubberduck.VBEditor.ComManagement.TypeLibsSupport;
using Rubberduck.VBEditor.Utility;
using TYPEATTR = System.Runtime.InteropServices.ComTypes.TYPEATTR;
using TYPEKIND = System.Runtime.InteropServices.ComTypes.TYPEKIND;
using TYPELIBATTR = System.Runtime.InteropServices.ComTypes.TYPELIBATTR;

namespace Rubberduck.Parsing.ComReflection
Expand Down Expand Up @@ -100,10 +101,10 @@ private void LoadModules(ITypeLib typeLibrary)
{
var typeAttributes = Marshal.PtrToStructure<TYPEATTR>(typeAttributesPointer);
KnownTypes.TryGetValue(typeAttributes.guid, out var type);

switch (typeAttributes.typekind)
switch (typeAttributes.typekind.ToTypeKindVbe())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that if we're going to assign TKIND_VBACLASS, we should at least make sure it's actually a VBA class at least.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How would you do that?

Moreover, nothing on a usual typelib should ever have the end of enum marker at TYPEKIND.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I originally thought of using the HasVBEExtensions function but looking at it, it might make more sense to simply set up the ComProject so that if it receives a VBE's ITypeLib from the TLAPI, set a property as a guard against mislabeling a non-VBA type info as VBA.

Alternatively, Wayne suggested simply casting it into TKIND_INTERFACE, since only the TLAPI cares about that distinction, but not the COM collector, right?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bclothier actually, I think this does need separate handling, since a TKIND_INTERFACE would not be expected to have any fields (cVars should be 0).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want to check the TKIND_VBACLASS value actually came from the type lib API, you could just test if the ITypeInfo casts to a TypeInfoWrapper.

{
case TYPEKIND.TKIND_ENUM:
case TYPEKIND_VBE.TKIND_ENUM:
var enumeration = type ?? new ComEnumeration(this, typeLibrary, info, typeAttributes, index);
Debug.Assert(enumeration is ComEnumeration);
_enumerations.Add(enumeration as ComEnumeration);
Expand All @@ -112,7 +113,7 @@ private void LoadModules(ITypeLib typeLibrary)
KnownTypes.TryAdd(typeAttributes.guid, enumeration);
}
break;
case TYPEKIND.TKIND_COCLASS:
case TYPEKIND_VBE.TKIND_COCLASS:
var coclass = type ?? new ComCoClass(this, typeLibrary, info, typeAttributes, index);
Debug.Assert(coclass is ComCoClass && !coclass.Guid.Equals(Guid.Empty));
_classes.Add(coclass as ComCoClass);
Expand All @@ -121,8 +122,8 @@ private void LoadModules(ITypeLib typeLibrary)
KnownTypes.TryAdd(typeAttributes.guid, coclass);
}
break;
case TYPEKIND.TKIND_DISPATCH:
case TYPEKIND.TKIND_INTERFACE:
case TYPEKIND_VBE.TKIND_DISPATCH:
case TYPEKIND_VBE.TKIND_INTERFACE:
var intface = type ?? new ComInterface(this, typeLibrary, info, typeAttributes, index);
Debug.Assert(intface is ComInterface && !intface.Guid.Equals(Guid.Empty));
_interfaces.Add(intface as ComInterface);
Expand All @@ -131,11 +132,11 @@ private void LoadModules(ITypeLib typeLibrary)
KnownTypes.TryAdd(typeAttributes.guid, intface);
}
break;
case TYPEKIND.TKIND_RECORD:
case TYPEKIND_VBE.TKIND_RECORD:
var structure = new ComStruct(this, typeLibrary, info, typeAttributes, index);
_structs.Add(structure);
break;
case TYPEKIND.TKIND_MODULE:
case TYPEKIND_VBE.TKIND_MODULE:
var module = type ?? new ComModule(this, typeLibrary, info, typeAttributes, index);
Debug.Assert(module is ComModule);
_modules.Add(module as ComModule);
Expand All @@ -144,17 +145,20 @@ private void LoadModules(ITypeLib typeLibrary)
KnownTypes.TryAdd(typeAttributes.guid, module);
}
break;
case TYPEKIND.TKIND_ALIAS:
case TYPEKIND_VBE.TKIND_ALIAS:
var alias = new ComAlias(this, typeLibrary, info, index, typeAttributes);
_aliases.Add(alias);
if (alias.Guid != Guid.Empty)
{
KnownAliases.TryAdd(alias.Guid, alias);
}
break;
case TYPEKIND.TKIND_UNION:
case TYPEKIND_VBE.TKIND_UNION:
//TKIND_UNION is not a supported member type in VBA.
break;
case TYPEKIND_VBE.TKIND_VBACLASS:
//TODO: Implement this.
break;
default:
throw new NotImplementedException($"Didn't expect a TYPEATTR with multiple typekind flags set in {Path}.");
}
Expand Down