Пример #1
0
        /// <summary>
        /// Exports the specified component to a temporary file, loads, and then parses the exported file.
        /// </summary>
        /// <param name="component"></param>
        public IDictionary<Tuple<string, DeclarationType>, Attributes> Parse(VBComponent component)
        {
            var path = _exporter.Export(component);
            if (!File.Exists(path))
            {
                // a document component without any code wouldn't be exported (file would be empty anyway).
                return new Dictionary<Tuple<string, DeclarationType>, Attributes>();
            }

            var code = File.ReadAllText(path);
            File.Delete(path);

            var type = component.Type == vbext_ComponentType.vbext_ct_StdModule
                ? DeclarationType.Module
                : DeclarationType.Class;
            var listener = new AttributeListener(Tuple.Create(component.Name, type));

            var stream = new AntlrInputStream(code);
            var lexer = new VBALexer(stream);
            var tokens = new CommonTokenStream(lexer);
            var parser = new VBAParser(tokens);

            // parse tree isn't usable for declarations because
            // line numbers are offset due to module header and attributes
            // (these don't show up in the VBE, that's why we're parsing an exported file)
            var tree = parser.startRule();
            ParseTreeWalker.Default.Walk(listener, tree);

            return listener.Attributes;
        }
        private static void ExportUserFormModule(VBComponent component, string path)
        {
            // VBIDE API inserts an extra newline when exporting a UserForm module.
            // this issue causes forms to always be treated as "modified" in source control, which causes conflicts.
            // we need to remove the extra newline before the file gets written to its output location.

            var visibleCode = component.CodeModule.Lines().Split(new []{Environment.NewLine}, StringSplitOptions.None);
            var legitEmptyLineCount = visibleCode.TakeWhile(string.IsNullOrWhiteSpace).Count();

            var tempFile = component.ExportToTempFile();
            var contents = File.ReadAllLines(tempFile);
            var nonAttributeLines = contents.TakeWhile(line => !line.StartsWith("Attribute")).Count();
            var attributeLines = contents.Skip(nonAttributeLines).TakeWhile(line => line.StartsWith("Attribute")).Count();
            var declarationsStartLine = nonAttributeLines + attributeLines + 1;

            var emptyLineCount = contents.Skip(declarationsStartLine - 1)
                                         .TakeWhile(string.IsNullOrWhiteSpace)
                                         .Count();

            var code = contents;
            if (emptyLineCount > legitEmptyLineCount)
            {
                code = contents.Take(declarationsStartLine).Union(
                       contents.Skip(declarationsStartLine + emptyLineCount - legitEmptyLineCount))
                               .ToArray();
            }
            File.WriteAllLines(path, code);
        }
        private static string GetNextTestMethodName(VBComponent component)
        {
            var names = component.TestMethods().Select(test => test.QualifiedMemberName.MemberName);
            var index = names.Count(n => n.StartsWith(TestMethodBaseName)) + 1;

            return string.Concat(TestMethodBaseName, index);
        }
 private void OnDispatch(EventHandler<DispatcherEventArgs<VBComponent>> dispatched, VBComponent component)
 {
     var handler = dispatched;
     if (handler != null)
     {
         handler.Invoke(this, new DispatcherEventArgs<VBComponent>(component));
     }
 }
 public void ItemRenamed(VBComponent VBComponent, string OldName)
 {
     var handler = ComponentRenamed;
     if (handler != null)
     {
         handler.Invoke(this, new DispatcherRenamedEventArgs<VBComponent>(VBComponent, OldName));
     }
 }
Пример #6
0
 public ComponentParseTask(VBComponent vbComponent, VBAPreprocessor preprocessor, IAttributeParser attributeParser, TokenStreamRewriter rewriter = null)
 {
     _attributeParser = attributeParser;
     _preprocessor = preprocessor;
     _component = vbComponent;
     _rewriter = rewriter;
     _qualifiedName = new QualifiedModuleName(vbComponent); 
 }
Пример #7
0
 public Mock<VBE> BuildFromSingleModule(string content, vbext_ComponentType type, out VBComponent component)
 {
     var builder = ProjectBuilder("TestProject1", vbext_ProjectProtection.vbext_pp_none);
     builder.AddComponent("TestModule1", type, content);
     var project = builder.Build();
     component = project.Object.VBComponents.Item(0);
     return AddProject(project).Build();
 }
        public void ItemRenamed(VBComponent VBComponent, string OldName)
        {
            var handler = ComponentRenamed;

            if (handler != null)
            {
                handler.Invoke(this, new DispatcherRenamedEventArgs <VBComponent>(VBComponent, OldName));
            }
        }
 private static void ExportDocumentModule(VBComponent component, string path)
 {
     var lineCount = component.CodeModule.CountOfLines;
     if (lineCount > 0)
     {
         var text = component.CodeModule.Lines[1, lineCount];
         File.WriteAllText(path, text);
     }
 }
Пример #10
0
        private void OnParseProgress(VBComponent component)
        {
            var handler = ParseProgress;

            if (handler != null)
            {
                handler(this, new ParseProgressEventArgs(component));
            }
        }
Пример #11
0
 public ComponentParseTask(VBComponent vbComponent, IVBAPreprocessor preprocessor, IAttributeParser attributeParser, TokenStreamRewriter rewriter = null)
 {
     _attributeParser = attributeParser;
     _preprocessor    = preprocessor;
     _component       = vbComponent;
     _rewriter        = rewriter;
     _qualifiedName   = new QualifiedModuleName(vbComponent);
     _parser          = new VBAModuleParser();
 }
Пример #12
0
        private void OnResolveProgress(VBComponent component)
        {
            var handler = ResolutionProgress;

            if (handler != null)
            {
                handler(this, new ResolutionProgressEventArgs(component));
            }
        }
Пример #13
0
        /// <summary>
        /// Ensures parser state accounts for built-in declarations.
        /// </summary>
        /// <summary>
        /// Requests reparse for specified component.
        /// Omit parameter to request a full reparse.
        /// </summary>
        /// <param name="requestor">The object requesting a reparse.</param>
        /// <param name="component">The component to reparse.</param>
        public void OnParseRequested(object requestor, VBComponent component = null)
        {
            var handler = ParseRequest;

            if (handler != null)
            {
                var args = new ParseRequestEventArgs(component);
                handler.Invoke(requestor, args);
            }
        }
Пример #14
0
        private static void ExportDocumentModule(VBComponent component, string path)
        {
            var lineCount = component.CodeModule.CountOfLines;

            if (lineCount > 0)
            {
                var text = component.CodeModule.Lines[1, lineCount];
                File.WriteAllText(path, text);
            }
        }
Пример #15
0
        private void LogParseException(VBComponent component, SyntaxErrorException exception)
        {
            var offendingProject   = component.Collection.Parent.Name;
            var offendingComponent = component.Name;
            var offendingLine      = component.CodeModule.get_Lines(exception.LineNumber, 1);

            var message = string.Format("Parser encountered a syntax error in {0}.{1}, line {2}. Content: '{3}'", offendingProject, offendingComponent, exception.LineNumber, offendingLine);

            _logger.ErrorException(message, exception);
        }
Пример #16
0
        private void OnModuleStateChanged(VBComponent component, ParserState state)
        {
            var handler = ModuleStateChanged;

            if (handler != null)
            {
                var args = new ParseProgressEventArgs(component, state);
                handler.Invoke(this, args);
            }
        }
Пример #17
0
        public IEnumerable <CommentNode> GetModuleComments(VBComponent component)
        {
            ModuleState state;

            if (_moduleStates.TryGetValue(new QualifiedModuleName(component), out state))
            {
                return(state.Comments);
            }

            return(new List <CommentNode>());
        }
        public IEnumerable <CommentNode> GetModuleComments(VBComponent component)
        {
            IList <CommentNode> result;

            if (_comments.TryGetValue(new QualifiedModuleName(component), out result))
            {
                return(result);
            }

            return(new List <CommentNode>());
        }
Пример #19
0
        public IEnumerable <IAnnotation> GetModuleAnnotations(VBComponent component)
        {
            ModuleState result;

            if (_moduleStates.TryGetValue(new QualifiedModuleName(component), out result))
            {
                return(result.Annotations);
            }

            return(new List <IAnnotation>());
        }
Пример #20
0
        /// <summary>
        /// Runs all methods with specified attribute.
        /// </summary>
        /// <typeparam name="TAttribute"></typeparam>
        /// <param name="component"></param>
        /// <remarks>
        /// Order of execution cannot be garanteed.
        /// </remarks>
        public static void RunMethodsWithAttribute <TAttribute>(this VBComponent component)
            where TAttribute : MemberAttributeBase, new()
        {
            var hostApp = component.VBE.HostApplication();
            var methods = component.GetMembers(vbext_ProcKind.vbext_pk_Proc)
                          .Where(member => member.HasAttribute <TAttribute>());

            foreach (var method in methods)
            {
                hostApp.Run(method.QualifiedMemberName);
            }
        }
Пример #21
0
        public static IEnumerable <TestMethod> TestMethods(this VBComponent component)
        {
            IHostApplication hostApp = component.VBE.HostApplication();

            if (component.Type == vbext_ComponentType.vbext_ct_StdModule && component.CodeModule.HasAttribute <TestModuleAttribute>())
            {
                return(component.GetMembers().Where(member => IsTestMethod(member))
                       .Select(member => new TestMethod(component.Collection.Parent.Name, component.Name, member.Name, hostApp)));
            }

            return(new List <TestMethod>());
        }
        public static IEnumerable <TestMethod> TestMethods(this VBComponent component)
        {
            if (component.Type == vbext_ComponentType.vbext_ct_StdModule &&
                component.CodeModule.HasAttribute <TestModuleAttribute>())
            {
                return(component.GetMembers()
                       .Where(IsTestMethod)
                       .Select(member => new TestMethod(member.QualifiedMemberName, component.VBE)));
            }

            return(new List <TestMethod>());
        }
Пример #23
0
        public QualifiedModuleName(VBComponent component)
        {
            _component       = component;
            _componentName   = component == null ? string.Empty : component.Name;
            _projectName     = component == null ? string.Empty : component.Collection.Parent.Name;
            _projectHashCode = component == null ? 0 : component.Collection.Parent.GetHashCode();

            var module = _component.CodeModule;

            _contentHashCode = module.CountOfLines > 0
                ? module.get_Lines(1, module.CountOfLines).GetHashCode()
                : 0;
        }
        private Declaration FindModuleDeclaration(VBComponent component)
        {
            var projectId = component.Collection.Parent.HelpFile;

            var project = _state.AllUserDeclarations.SingleOrDefault(item => 
                item.DeclarationType == DeclarationType.Project && item.ProjectId == projectId);

            var result = _state.AllUserDeclarations.SingleOrDefault(item => item.ProjectId == component.Collection.Parent.HelpFile
                                                             && item.QualifiedName.QualifiedModuleName.ComponentName == component.Name
                                                             && (item.DeclarationType == DeclarationType.Class || item.DeclarationType == DeclarationType.Module));

            var declaration = new Declaration(new QualifiedMemberName(new QualifiedModuleName(component), component.Name), project, project.Scope, component.Name, false, false, Accessibility.Global, DeclarationType.Module, false);
            return result ?? declaration; // module isn't in parser state - give it a dummy declaration, just so the ViewModel has something to chew on
        }
        public VBComponentParseResult(VBComponent component, IParseTree parseTree, IEnumerable<CommentNode> comments, ITokenStream tokenStream)
        {
            _component = component;
            _qualifiedName = new QualifiedModuleName(component);
            _parseTree = parseTree;
            _comments = comments;
            _tokenStream = tokenStream;

            var listener = new DeclarationSymbolsListener(_qualifiedName, Accessibility.Implicit, _component.Type);
            var walker = new ParseTreeWalker();
            walker.Walk(listener, _parseTree);

            _declarations.AddRange(listener.Declarations.Items);
        }
Пример #26
0
        private void OnParserError(SyntaxErrorException exception, VBComponent component)
        {
            if (LogManager.IsLoggingEnabled())
            {
                LogParseException(exception, component);
            }

            var handler = ParserError;

            if (handler != null)
            {
                handler(this, new ParseErrorEventArgs(exception, component));
            }
        }
Пример #27
0
        private Task ParseAsync(VBComponent component, CancellationTokenSource token, TokenStreamRewriter rewriter = null)
        {
            State.ClearStateCache(component);

            var task = new Task(() => ParseAsyncInternal(component, token.Token, rewriter));

            _currentTasks.TryAdd(component, Tuple.Create(task, token));

            Tuple <Task, CancellationTokenSource> removedTask;

            task.ContinueWith(t => _currentTasks.TryRemove(component, out removedTask), token.Token); // default also executes on cancel
            // See http://stackoverflow.com/questions/6800705/why-is-taskscheduler-current-the-default-taskscheduler
            task.Start(TaskScheduler.Default);
            return(task);
        }
Пример #28
0
        public QualifiedModuleName(VBComponent component)
        {
            _project = null; // field is only assigned when the instance refers to a VBProject.

            _component       = component;
            _componentName   = component == null ? string.Empty : component.Name;
            _projectName     = component == null ? string.Empty : component.Collection.Parent.Name;
            _projectHashCode = component == null ? 0 : component.Collection.Parent.GetHashCode();

            var module = _component.CodeModule;

            _contentHashCode = module.CountOfLines > 0
                ? module.get_Lines(1, module.CountOfLines).GetHashCode()
                : 0;
        }
Пример #29
0
        public VBComponentParseResult(VBComponent component, IParseTree parseTree, IEnumerable <CommentNode> comments, ITokenStream tokenStream)
        {
            _component     = component;
            _qualifiedName = new QualifiedModuleName(component);
            _parseTree     = parseTree;
            _comments      = comments;
            _tokenStream   = tokenStream;

            var listener = new DeclarationSymbolsListener(_qualifiedName, Accessibility.Implicit, _component.Type);
            var walker   = new ParseTreeWalker();

            walker.Walk(listener, _parseTree);

            _declarations.AddRange(listener.Declarations.Items);
        }
Пример #30
0
        public QualifiedModuleName(VBComponent component)
        {
            _project = null; // field is only assigned when the instance refers to a VBProject.

            _component = component;
            _componentName = component == null ? string.Empty : component.Name;
            _projectName = component == null ? string.Empty : component.Collection.Parent.Name;
            _projectHashCode = component == null ? 0 : component.Collection.Parent.GetHashCode();

            var module = _component.CodeModule;

            _contentHashCode = module.CountOfLines > 0 
                ? module.get_Lines(1, module.CountOfLines).GetHashCode() 
                : 0;
        }
Пример #31
0
        private Declaration FindModuleDeclaration(VBComponent component)
        {
            var projectId = component.Collection.Parent.HelpFile;

            var project = _state.AllUserDeclarations.SingleOrDefault(item =>
                                                                     item.DeclarationType == DeclarationType.Project && item.ProjectId == projectId);

            var result = _state.AllUserDeclarations.SingleOrDefault(item => item.ProjectId == component.Collection.Parent.HelpFile &&
                                                                    item.QualifiedName.QualifiedModuleName.ComponentName == component.Name &&
                                                                    (item.DeclarationType == DeclarationType.ClassModule || item.DeclarationType == DeclarationType.ProceduralModule));

            var declaration = new Declaration(new QualifiedMemberName(new QualifiedModuleName(component), component.Name), project, project.Scope, component.Name, false, false, Accessibility.Global, DeclarationType.ProceduralModule, false);

            return(result ?? declaration); // module isn't in parser state - give it a dummy declaration, just so the ViewModel has something to chew on
        }
Пример #32
0
        /// <summary>
        /// Scans form designer to create a public, self-assigned field for each control on a form.
        /// </summary>
        /// <remarks>
        /// These declarations are meant to be used to identify control event procedures.
        /// </remarks>
        private void DeclareControlsAsMembers(VBComponent form)
        {
            var designer = form.Designer;

            if (designer == null)
            {
                return;
            }

            // using dynamic typing here, because not only MSForms could have a Controls collection (e.g. MS-Access forms are 'document' modules).
            foreach (var control in ((dynamic)designer).Controls)
            {
                var declaration = new Declaration(_qualifiedName.QualifyMemberName(control.Name), _parentDeclaration, _currentScopeDeclaration, "Control", true, true, Accessibility.Public, DeclarationType.Control, null, Selection.Home);
                OnNewDeclaration(declaration);
            }
        }
Пример #33
0
        public override void Execute(object parameter)
        {
            var declarations       = _state.AllDeclarations;
            var qualifiedSelection = Vbe.ActiveCodePane.GetQualifiedSelection();

            var extractMethodValidation = new ExtractMethodSelectionValidation(declarations);
            var canExecute = extractMethodValidation.withinSingleProcedure(qualifiedSelection.Value);

            if (!canExecute)
            {
                return;
            }
            ICodeModuleWrapper codeModuleWrapper = new CodeModuleWrapper(Vbe.ActiveCodePane.CodeModule);
            VBComponent        vbComponent       = Vbe.SelectedVBComponent;

            Func <QualifiedSelection?, string, IExtractMethodModel> createMethodModel = (qs, code) =>
            {
                if (qs == null)
                {
                    return(null);
                }
                //TODO: Pull these even further back;
                //      and implement with IProvider<IExtractMethodRule>
                var rules = new List <IExtractMethodRule>()
                {
                    new ExtractMethodRuleInSelection(),
                    new ExtractMethodRuleIsAssignedInSelection(),
                    new ExtractMethodRuleUsedAfter(),
                    new ExtractMethodRuleUsedBefore()
                };

                var paramClassify = new ExtractMethodParameterClassification(rules);

                var extractedMethod      = new ExtractedMethod();
                var extractedMethodModel = new ExtractMethodModel(extractedMethod, paramClassify);
                extractedMethodModel.extract(declarations, qs.Value, code);
                return(extractedMethodModel);
            };

            var             extraction   = new ExtractMethodExtraction();
            Action <Object> parseRequest = (obj) => _state.OnParseRequested(obj, vbComponent);

            var refactoring = new ExtractMethodRefactoring(codeModuleWrapper, parseRequest, createMethodModel, extraction);

            refactoring.InvalidSelection += HandleInvalidSelection;
            refactoring.Refactor();
        }
 /// <summary>
 /// Safely removes the specified VbComponent from the collection.
 /// </summary>
 /// <remarks>
 /// UserForms, Class modules, and Standard modules are completely removed from the project.
 /// Since Document type components can't be removed through the VBE, all code in its CodeModule are deleted instead.
 /// </remarks>
 public static void RemoveSafely(this VBComponents components, VBComponent component)
 {
     switch (component.Type)
     {
         case vbext_ComponentType.vbext_ct_ClassModule:
         case vbext_ComponentType.vbext_ct_StdModule:
         case vbext_ComponentType.vbext_ct_MSForm:
             components.Remove(component);
             break;
         case vbext_ComponentType.vbext_ct_ActiveXDesigner:
         case vbext_ComponentType.vbext_ct_Document:
             component.CodeModule.Clear();
             break;
         default:
             break;
     }
 }
Пример #35
0
 /// <summary>
 /// Safely removes the specified VbComponent from the collection.
 /// </summary>
 /// <remarks>
 /// UserForms, Class modules, and Standard modules are completely removed from the project.
 /// Since Document type components can't be removed through the VBE, all code in its CodeModule are deleted instead.
 /// </remarks>
 public static void RemoveSafely(this VBComponents components, VBComponent component)
 {
     switch (component.Type)
     {
         case vbext_ComponentType.vbext_ct_ClassModule:
         case vbext_ComponentType.vbext_ct_StdModule:
         case vbext_ComponentType.vbext_ct_MSForm:
             components.Remove(component);
             break;
         case vbext_ComponentType.vbext_ct_ActiveXDesigner:
         case vbext_ComponentType.vbext_ct_Document:
             component.CodeModule.Clear();
             break;
         default:
             break;
     }
 }
Пример #36
0
        private void bruteforce()
        {
            lbl_status.Text      = "In progress...";
            lbl_status.ForeColor = Color.Orange;

            try
            {
                InitRegKey();
                var       excel = new Application();
                var       wbs   = excel.Workbooks;
                Workbook  wb    = wbs.Open(filename);
                Worksheet sheet = (Worksheet)wb.ActiveSheet;

                /*if (wb.HasVBProject)
                 * {*/
                VBProject project = wb.VBProject;

                VBComponent module = project.VBComponents.Add(vbext_ComponentType.vbext_ct_StdModule);
                module.CodeModule.AddFromString(script);

                wb.Application.Run("Unlocker");
                excel.Visible     = false;
                excel.UserControl = false;
                //}
                project.VBComponents.Remove(module);

                wb.Save();
                wb.Close();
                excel.Workbooks.Close();
                excel.Quit();
            }
            catch (Exception e)
            {
                lbl_status.Text      = "Failed";
                lbl_status.ForeColor = Color.Red;
            }

            lbl_status.Text      = "Success!";
            lbl_status.ForeColor = Color.Green;

            //vba scripts:
            //http://jsbi.blogspot.com/2008/09/how-to-easily-unprotectremove-password.html
            //https://exceloffthegrid.com/removing-cracking-excel-passwords-with-vba/
            //details sur la methode de hash d'excel
            //https://stackoverflow.com/questions/19953979/cracking-sheet-password-with-vba/19958159
        }
Пример #37
0
        private Declaration CreateDeclaration(VBComponent component)
        {
            var projectDeclaration =
                _state.AllUserDeclarations.FirstOrDefault(item =>
                                                          item.DeclarationType == DeclarationType.Project &&
                                                          item.Project.VBComponents.Cast <VBComponent>().Contains(component));

            if (component.Type == vbext_ComponentType.vbext_ct_StdModule)
            {
                return(new ProceduralModuleDeclaration(
                           new QualifiedMemberName(new QualifiedModuleName(component), component.Name), projectDeclaration,
                           component.Name, false, new List <IAnnotation>(), null));
            }

            return(new ClassModuleDeclaration(new QualifiedMemberName(new QualifiedModuleName(component), component.Name),
                                              projectDeclaration, component.Name, false, new List <IAnnotation>(), null));
        }
Пример #38
0
        private void ResolveDeclarations(VBComponent component, IParseTree tree)
        {
            var qualifiedModuleName = new QualifiedModuleName(component);

            var obsoleteCallStatementListener    = new ObsoleteCallStatementListener();
            var obsoleteLetStatementListener     = new ObsoleteLetStatementListener();
            var emptyStringLiteralListener       = new EmptyStringLiteralListener();
            var argListWithOneByRefParamListener = new ArgListWithOneByRefParamListener();

            try
            {
                ParseTreeWalker.Default.Walk(new CombinedParseTreeListener(new IParseTreeListener[] {
                    obsoleteCallStatementListener,
                    obsoleteLetStatementListener,
                    emptyStringLiteralListener,
                    argListWithOneByRefParamListener,
                }), tree);
                // TODO: these are actually (almost) inspection results.. we should handle them as such
                _state.ArgListsWithOneByRefParam = argListWithOneByRefParamListener.Contexts.Select(context => new QualifiedContext(qualifiedModuleName, context));
                _state.EmptyStringLiterals       = emptyStringLiteralListener.Contexts.Select(context => new QualifiedContext(qualifiedModuleName, context));
                _state.ObsoleteLetContexts       = obsoleteLetStatementListener.Contexts.Select(context => new QualifiedContext(qualifiedModuleName, context));
                _state.ObsoleteCallContexts      = obsoleteCallStatementListener.Contexts.Select(context => new QualifiedContext(qualifiedModuleName, context));
                var         project = component.Collection.Parent;
                var         projectQualifiedName = new QualifiedModuleName(project);
                Declaration projectDeclaration;
                if (!_projectDeclarations.TryGetValue(projectQualifiedName.ProjectId, out projectDeclaration))
                {
                    projectDeclaration = CreateProjectDeclaration(projectQualifiedName, project);
                    _projectDeclarations.Add(projectQualifiedName.ProjectId, projectDeclaration);
                    _state.AddDeclaration(projectDeclaration);
                }
                var declarationsListener = new DeclarationSymbolsListener(qualifiedModuleName, Accessibility.Implicit, component.Type, _state.GetModuleComments(component), _state.GetModuleAnnotations(component), _state.GetModuleAttributes(component), _projectReferences, projectDeclaration);
                // TODO: should we unify the API? consider working like the other listeners instead of event-based
                declarationsListener.NewDeclaration += (sender, e) => _state.AddDeclaration(e.Declaration);
                declarationsListener.CreateModuleDeclarations();
                // rewalk parse tree for second declaration level

                Debug.WriteLine("Walking parse tree for '{0}'... (acquiring declarations)", qualifiedModuleName.Name);
                ParseTreeWalker.Default.Walk(declarationsListener, tree);
            } catch (Exception exception)
            {
                Debug.Print("Exception thrown acquiring declarations for '{0}' (thread {2}): {1}", component.Name, exception, Thread.CurrentThread.ManagedThreadId);
                _state.SetModuleState(component, ParserState.ResolverError);
            }
        }
        /// <summary>
        /// Scans form designer to create a public, self-assigned field for each control on a form.
        /// </summary>
        /// <remarks>
        /// These declarations are meant to be used to identify control event procedures.
        /// </remarks>
        private void DeclareControlsAsMembers(VBComponent form)
        {
            if (form.Type != vbext_ComponentType.vbext_ct_MSForm)
            {
                throw new InvalidOperationException();
            }

            var designer = form.Designer;
            if (designer == null)
            {
                return;
            }

            foreach (var control in ((dynamic)designer).Controls)
            {
                _declarations.Add(new Declaration(_qualifiedName.QualifyMemberName(control.Name), _currentScope, "Control", true, true, Accessibility.Public, DeclarationType.Control, null, Selection.Home));
            }
        }
Пример #40
0
        /// <summary>
        /// Exports the component to the directoryPath. The file is name matches the component name and file extension is based on the component's type.
        /// </summary>
        /// <param name="component">The component to be exported to the file system.</param>
        /// <param name="directoryPath">Destination Path for the resulting source file.</param>
        public static void ExportAsSourceFile(this VBComponent component, string directoryPath)
        {
            string filePath = Path.Combine(directoryPath, component.Name + component.Type.FileExtension());

            if (component.Type == vbext_ComponentType.vbext_ct_Document)
            {
                int lineCount = component.CodeModule.CountOfLines;
                if (lineCount > 0)
                {
                    var text = component.CodeModule.get_Lines(1, lineCount);
                    File.WriteAllText(filePath, text);
                }
            }
            else
            {
                component.Export(filePath);
            }
        }
Пример #41
0
        public ParserState GetOrCreateModuleState(VBComponent component)
        {
            var key   = new QualifiedModuleName(component);
            var state = _moduleStates.GetOrAdd(key, new ModuleState(ParserState.Pending)).State;

            if (state == ParserState.Pending)
            {
                return(state);   // we are slated for a reparse already
            }

            if (!IsNewOrModified(key))
            {
                return(state);
            }

            _moduleStates.AddOrUpdate(key, new ModuleState(ParserState.Pending), (c, s) => s.SetState(ParserState.Pending));
            return(ParserState.Pending);
        }
Пример #42
0
        public void HandleRemovedComponent(VBComponent component)
        {
            if (Provider == null || !Provider.HandleVbeSinkEvents)
            {
                return;
            }

            if (component.Collection.Parent.HelpFile != Provider.CurrentRepository.Id)
            {
                return;
            }

            var fileStatus = Provider.Status().SingleOrDefault(stat => stat.FilePath.Split('.')[0] == component.Name);

            if (fileStatus != null)
            {
                Provider.RemoveFile(fileStatus.FilePath, true);
            }
        }
Пример #43
0
        public Task ParseAsync(VBComponent component, CancellationToken token, TokenStreamRewriter rewriter = null)
        {
            _state.ClearStateCache(component);
            _state.SetModuleState(component, ParserState.Pending); // also clears module-exceptions

            var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(_central.Token, token);

            //var taskFactory = new TaskFactory(new StaTaskScheduler());
            var task = new Task(() => ParseAsyncInternal(component, linkedTokenSource.Token, rewriter));

            _currentTasks.TryAdd(component, Tuple.Create(task, linkedTokenSource));

            Tuple <Task, CancellationTokenSource> removedTask;

            task.ContinueWith(t => _currentTasks.TryRemove(component, out removedTask)); // default also executes on cancel

            task.Start(/*taskFactory.Scheduler*/);
            return(task);
        }
Пример #44
0
        public QualifiedModuleName(VBComponent component)
        {
            _project = null; // field is only assigned when the instance refers to a VBProject.

            _component = component;
            _componentName = component == null ? string.Empty : component.Name;
            _project = component == null ? null : component.Collection.Parent;
            _projectName = _project == null ? string.Empty : _project.Name;
            _projectPath = string.Empty;
            _projectId = GetProjectId(_project);

            _contentHashCode = 0;
            if (component == null)
            {
                return;
            }

            var module = component.CodeModule;
            _contentHashCode = module.CountOfLines > 0
                // ReSharper disable once UseIndexedProperty
                ? module.get_Lines(1, module.CountOfLines).GetHashCode()
                : 0;
        }
Пример #45
0
        private VBComponentParseResult Parse(VBComponent component, out bool cached)
        {
            try
            {
                VBComponentParseResult cachedValue;
                var name = new QualifiedModuleName(component); // already a performance hit
                if (ParseResultCache.TryGetValue(name, out cachedValue))
                {
                    cached = true;
                    return cachedValue;
                }

                var codeModule = component.CodeModule;
                var lines = codeModule.Lines();

                ITokenStream stream;
                var parseTree = Parse(lines, out stream);
                var comments = ParseComments(name);
                var result = new VBComponentParseResult(component, parseTree, comments, stream);

                var existing = ParseResultCache.Keys.SingleOrDefault(k => k.Project == name.Project && k.ComponentName == name.ComponentName);
                VBComponentParseResult removed;
                ParseResultCache.TryRemove(existing, out removed);
                ParseResultCache.AddOrUpdate(name, module => result, (qName, module) => result);

                cached = false;
                return result;
            }
            catch (SyntaxErrorException exception)
            {
                OnParserError(exception, component);
                cached = false;
                return null;
            }
            catch (COMException)
            {
                cached = false;
                return null;
            }
        }
Пример #46
0
        private void ResolveReferences(DeclarationFinder finder, VBComponent component, IParseTree tree)
        {
            var state = _state.GetModuleState(component);
            if (_state.Status == ParserState.ResolverError || (state != ParserState.Parsed))
            {
                return;
            }

            Debug.WriteLine("Resolving '{0}'... (thread {1})", component.Name, Thread.CurrentThread.ManagedThreadId);            
            var qualifiedName = new QualifiedModuleName(component);
            var resolver = new IdentifierReferenceResolver(qualifiedName, finder);
            var listener = new IdentifierReferenceListener(resolver);
            if (!string.IsNullOrWhiteSpace(tree.GetText().Trim()))
            {
                var walker = new ParseTreeWalker();
                try
                {
                    walker.Walk(listener, tree);
                    state = ParserState.Ready;
                }
                catch (Exception exception)
                {
                    Debug.Print("Exception thrown resolving '{0}' (thread {2}): {1}", component.Name, exception, Thread.CurrentThread.ManagedThreadId);
                    state = ParserState.ResolverError;
                }
            }

            _state.SetModuleState(component, state);
            Debug.Print("'{0}' is {1}. Resolver took {2}ms to complete (thread {3})", component.Name, _state.GetModuleState(component), /*_resolverTimer[component].ElapsedMilliseconds*/0, Thread.CurrentThread.ManagedThreadId);
        }
Пример #47
0
 private void LogVbComponent(VBComponent vbComponent)
 {
     Log(vbComponent.Name + " (" + vbComponent.Type.AsString() + ")");
 }
Пример #48
0
 private static string GetFileExtensionFor(VBComponent vbComp)
 {
     switch (vbComp.Type) {
         case vbext_ComponentType.vbext_ct_ClassModule:
             return ".cls";
         case vbext_ComponentType.vbext_ct_Document:
             return ".wks";
         case vbext_ComponentType.vbext_ct_MSForm:
             return ".frm";
         case vbext_ComponentType.vbext_ct_StdModule:
             return ".bas";
         default:
             return ".bas";
     }
 }
Пример #49
0
        public Task ParseAsync(VBComponent component, CancellationToken token, TokenStreamRewriter rewriter = null)
        {
            _state.ClearDeclarations(component);            
            _state.SetModuleState(component, ParserState.Pending); // also clears module-exceptions

            var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(_central.Token, token);

            //var taskFactory = new TaskFactory(new StaTaskScheduler());
            var task = new Task(() => ParseAsyncInternal(component, linkedTokenSource.Token, rewriter));
            _currentTasks.TryAdd(component, Tuple.Create(task, linkedTokenSource));

            Tuple<Task, CancellationTokenSource> removedTask;
            task.ContinueWith(t => _currentTasks.TryRemove(component, out removedTask)); // default also executes on cancel

            task.Start(/*taskFactory.Scheduler*/);
            return task;
        }
Пример #50
0
 private string QualifyComponentName(VBComponent component)
 {
     return component.Collection.Parent.Name + "." + component.Name;
 }
Пример #51
0
 private void OnParseProgress(VBComponent component)
 {
     var handler = ParseProgress;
     if (handler != null)
     {
         handler(this, new ParseProgressEventArgs(component));
     }
 }
Пример #52
0
 private void OnResolveProgress(VBComponent component)
 {
     var handler = ResolutionProgress;
     if (handler != null)
     {
         handler(this, new ResolutionProgressEventArgs(component));
     }
 }
Пример #53
0
        private void LogParseException(SyntaxErrorException exception, VBComponent component)
        {
            var offendingProject = component.Collection.Parent.Name;
            var offendingComponent = component.Name;
            var offendingLine = component.CodeModule.get_Lines(exception.LineNumber, 1);

            var message = string.Format("Parser encountered a syntax error in {0}.{1}, line {2}. Content: '{3}'", offendingProject, offendingComponent, exception.LineNumber, offendingLine);
            _logger.ErrorException(message, exception);
        }
Пример #54
0
        private void ResolveDeclarations(VBComponent component, IParseTree tree)
        {
            var qualifiedModuleName = new QualifiedModuleName(component);

            var obsoleteCallStatementListener = new ObsoleteCallStatementListener();
            var obsoleteLetStatementListener = new ObsoleteLetStatementListener();
            var emptyStringLiteralListener = new EmptyStringLiteralListener();
            var argListWithOneByRefParamListener = new ArgListWithOneByRefParamListener();
            
            try
            {
                ParseTreeWalker.Default.Walk(new CombinedParseTreeListener(new IParseTreeListener[]{
                    obsoleteCallStatementListener,
                    obsoleteLetStatementListener,
                    emptyStringLiteralListener,
                    argListWithOneByRefParamListener,
                }), tree);
                // TODO: these are actually (almost) isnpection results.. we should handle them as such
                _state.ArgListsWithOneByRefParam = argListWithOneByRefParamListener.Contexts.Select(context => new QualifiedContext(qualifiedModuleName, context));
                _state.EmptyStringLiterals = emptyStringLiteralListener.Contexts.Select(context => new QualifiedContext(qualifiedModuleName, context));
                _state.ObsoleteLetContexts = obsoleteLetStatementListener.Contexts.Select(context => new QualifiedContext(qualifiedModuleName, context));
                _state.ObsoleteCallContexts = obsoleteCallStatementListener.Contexts.Select(context => new QualifiedContext(qualifiedModuleName, context));

                // cannot locate declarations in one pass *the way it's currently implemented*,
                // because the context in EnterSubStmt() doesn't *yet* have child nodes when the context enters.
                // so we need to EnterAmbiguousIdentifier() and evaluate the parent instead - this *might* work.
                var declarationsListener = new DeclarationSymbolsListener(qualifiedModuleName, Accessibility.Implicit, component.Type, _state.GetModuleComments(component), _state.GetModuleAnnotations(component),_state.GetModuleAttributes(component), _references);
                // TODO: should we unify the API? consider working like the other listeners instead of event-based
                declarationsListener.NewDeclaration += (sender, e) => _state.AddDeclaration(e.Declaration);
                declarationsListener.CreateModuleDeclarations();
                // rewalk parse tree for second declaration level
                ParseTreeWalker.Default.Walk(declarationsListener, tree);
            } catch (Exception exception)
            {
                Debug.Print("Exception thrown resolving '{0}' (thread {2}): {1}", component.Name, exception, Thread.CurrentThread.ManagedThreadId);
                _state.SetModuleState(component, ParserState.ResolverError);
            }

        }
Пример #55
0
        public void ExtractVBComponent(VBComponent comp, string path, string fName, bool overwrite)
        {
            // do we need to export component?
            if (comp.CodeModule.CountOfLines == 0) {
                return;
            }

            // define file name
            var extension = GetFileExtensionFor(comp);
            if (fName.Trim() == String.Empty) {
                fName = comp.Name + extension;
            } else if (fName.IndexOf("."[0]) == 0) {
                fName = fName + extension;
            }

            // define folder path
            if (path.EndsWith(@"\", StringComparison.CurrentCultureIgnoreCase)) {
                fName = path + fName;
            } else {
                fName = path + @"\" + fName;
            }

            // is it possible to write to path
            FileInfo file = new FileInfo(fName);
            if (file.Exists) {
                if (overwrite) {
                    file.Delete();
                }
            }

            comp.Export(fName);
        }
Пример #56
0
        private void ParseAsyncInternal(VBComponent component, CancellationToken token, TokenStreamRewriter rewriter = null)
        {
            var preprocessor = new VBAPreprocessor(double.Parse(_vbe.Version, CultureInfo.InvariantCulture));
            var parser = new ComponentParseTask(component, preprocessor, _attributeParser, rewriter);
            parser.ParseFailure += (sender, e) => _state.SetModuleState(component, ParserState.Error, e.Cause as SyntaxErrorException);
            parser.ParseCompleted += (sender, e) =>
            {
                // possibly lock _state
                _state.SetModuleAttributes(component, e.Attributes);
                _state.AddParseTree(component, e.ParseTree);
                _state.AddTokenStream(component, e.Tokens);
                _state.SetModuleComments(component, e.Comments);
                _state.SetModuleAnnotations(component, e.Annotations);

                // This really needs to go last
                _state.SetModuleState(component, ParserState.Parsed);
            };
            _state.SetModuleState(component, ParserState.Parsing);
            parser.Start(token);
        }
Пример #57
0
        public void Cancel(VBComponent component = null)
        {
            lock (_central)
            lock (_resolverTokenSource)
            {
                if (component == null)
                {
                    _central.Cancel(false);

                    _central.Dispose();
                    _central = new CancellationTokenSource();
                    _resolverTokenSource = CancellationTokenSource.CreateLinkedTokenSource(_central.Token);
                }
                else
                {
                    _resolverTokenSource.Cancel(false);
                    _resolverTokenSource.Dispose();

                    _resolverTokenSource = CancellationTokenSource.CreateLinkedTokenSource(_central.Token);
                    Tuple<Task, CancellationTokenSource> result;
                    if (_currentTasks.TryGetValue(component, out result))
                    {
                        result.Item2.Cancel(false);
                        result.Item2.Dispose();
                    }
                }
            }
        }
Пример #58
0
 public string Export(VBComponent component)
 {
     return component.ExportAsSourceFile(ExportPath);
 }
Пример #59
0
        private void OnParserError(SyntaxErrorException exception, VBComponent component)
        {
            if (LogManager.IsLoggingEnabled())
            {
                LogParseException(exception, component);
            }

            var handler = ParserError;
            if (handler != null)
            {
                handler(this, new ParseErrorEventArgs(exception, component));
            }
        }
Пример #60
0
 private void ParseComponent(VBComponent component, TokenStreamRewriter rewriter = null)
 {
     ParseAsync(component, CancellationToken.None, rewriter).Wait();
 }