Exemplo n.º 1
0
        /// <summary>
        /// Returns project files.
        /// </summary>
        private void GetFilesInternal(object project, List <FileModel> model, ProcessorFlags flags, CodeModelFilterFlags filter)
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            var dteProject = project as Project;

            if (dteProject == null)
            {
                throw new ArgumentNullException(nameof(project));
            }

            if (_shellProjectService.IsProjectLoadDeferred(project, out _))
            {
                return;
            }

            _log.LogMessage($"Collecting '{dteProject.Name}' project files", LOG_CATEGORY);

            // No need to process project's items if we fail to check its code model
            // The exception is made for solution folder *if* that's requested
            var  languageSet = _fileTypeResolver.GetCurrentLanguage(project, out bool isWebProject);
            bool process     = languageSet != null;

            if (!process)
            {
                if (flags.HasFlag(ProcessorFlags.IncludeSolutionFolderFiles) && (dteProject.Kind == Constants.vsProjectKindSolutionItems))
                {
                    _log.LogMessage($"Allow '{dteProject.Name}' solution folder processing", LOG_CATEGORY);
                    process = true;
                }
            }

            if (!process && !flags.HasFlag(ProcessorFlags.KnownProjectsOnly) && _shellProjectService.IsProject(project))
            {
                _log.LogMessage($"Allow '{dteProject.Name}' unknown project type processing", LOG_CATEGORY);
                process = true;
            }

            if (process)
            {
                ProjectItems projectItems = dteProject.ProjectItems;
                if ((projectItems != null) && (projectItems.Count > 0))
                {
                    bool isRoot = true;
                    ProcessProjectItems(
                        model, flags, filter, languageSet,
                        projectItems, isWebProject, ref isRoot, null, string.Empty);
                }
            }

            _log.LogMessage($"Collected {model.Count} '{dteProject.Name}' project files", LOG_CATEGORY);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Returns solution projects.
        /// </summary>
        private void GetProjectsInternal(SolutionModel model, ProcessorFlags flags, CodeModelFilterFlags filter)
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            var dte = _shellProjectService.GetDTE() as DTE;

            _log.LogMessage("Collecting solution projects");

            var projects = dte.Solution.Projects;

            for (int index = 1; index <= projects.Count; index++)
            {
                Project project = projects.Item(index);

                if (_shellProjectService.IsProjectLoadDeferred(project, out bool loaded))
                {
                    continue;
                }

                // Reacquire project reference if it's been reloaded
                if (loaded)
                {
                    project = projects.Item(index);
                }

                if (ProcessProject(project, model.Projects, flags, filter))
                {
                    ProcessProjectRecursively(project, model.Projects, flags, filter);
                }
            }

            model.Files = model.Projects.SelectMany(p => p.Files).ToList();

            if (flags.HasFlag(ProcessorFlags.GroupLinkedFiles))
            {
                // Get all grouped, ie duplicate, files, keep the first code file and remove the rest
                var groupedFiles = model.Files.GroupBy(f => f.FileNameWithPath).Where(g => g.Count() > 1).Select(g => g);
                foreach (var group in groupedFiles)
                {
                    var file = group.FirstOrDefault(f => f.Project.Language.SupportsCompileBuildAction && _shellProjectService.CompileBuildAction(f.ProjectItem));
                    if (file != null)
                    {
                        group.ForEach(f =>
                        {
                            if (f != file)
                            {
                                model.Files.Remove(f);
                                f.Project.Files.Remove(f);
                                AddProjectName(file, f.ProjectName);
                            }
                        });
                    }
                }
            }

            _log.LogMessage($"Collected {model.Projects.Count} solution projects");
        }
Exemplo n.º 3
0
		public async Task<string> ProcessAsync(string name, string[] files, ProcessorFlags flags, string basePath)
		{
			var bundler = _container.Resolve<IAssetBundler>();
			var result = await bundler.BundleAsync(_assetHelper.GetGlobComponentsForAsset(files, basePath));

			var factory = _container.Resolve<IAssetCompilerFactory>();
			var compiler = factory.GetCompiler(name);

            return await compiler.CompileAsync(result, flags.HasFlag(ProcessorFlags.Minify));
		}
Exemplo n.º 4
0
        public async Task <string> ProcessAsync(string name, string[] files, ProcessorFlags flags, string basePath)
        {
            var bundler = _container.Resolve <IAssetBundler>();
            var result  = await bundler.BundleAsync(_assetHelper.GetGlobComponentsForAsset(files, basePath));

            var factory  = _container.Resolve <IAssetCompilerFactory>();
            var compiler = factory.GetCompiler(name);

            return(await compiler.CompileAsync(result, flags.HasFlag(ProcessorFlags.Minify)));
        }
Exemplo n.º 5
0
        /// <summary>
        /// Walks qualified project items and processes all of their qualified items.
        /// </summary>
        private void ProcessProjectItems(List <FileModel> model, ProcessorFlags flags, CodeModelFilterFlags filter, LanguageSettings languageSet,
                                         ProjectItems projectItems, bool isWebProject, ref bool isRoot, ProjectItem parentItem, string parentName)
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            // Parent item is applicable or meant to be used for actual files only, i.e. file combos like .cs and .designer.cs, etc.
            if (parentItem != null)
            {
                var parentItemKind = parentItem.Kind;

                if ((string.Compare(parentItemKind, Constants.vsProjectItemKindPhysicalFile, StringComparison.OrdinalIgnoreCase) != 0) &&
                    (string.Compare(parentItemKind, Constants.vsProjectItemKindSolutionItems, StringComparison.OrdinalIgnoreCase) != 0))
                {
                    parentItem = null;
                }
            }
            var parentSubType    = FileSubType.None;
            var parentSubTypeSet = false;

            if (!string.IsNullOrEmpty(parentName) && !parentName.EndsWith("\\", StringComparison.OrdinalIgnoreCase))
            {
                parentName = parentName + "\\";
            }

            // Save the current language and determine the new current language
            if (isWebProject)
            {
                var webLanguageSet = GetWebFolderLanguage(isRoot, projectItems);

                // Fallback scenario - use default project language so that non-code files can be resolved
                if (webLanguageSet?.Type != LanguageType.Unknown)
                {
                    languageSet = webLanguageSet;                     // language should be restored for other items once we walk up the stack
                }
            }

            // Root processing is finished after language is checked for the root project items
            isRoot = false;
            var projectName = string.Empty;

            foreach (ProjectItem projectItem in projectItems)
            {
                // Skip project references as they can't contribute any files
                var isReferences = projectItem.Object is VSLangProj.References;
                var isReference  = projectItem.Object is VSLangProj.Reference;
                if (isReferences || isReference)
                {
                    continue;
                }

                var projectItemKind = projectItem.Kind;

                // LightSwitch type projects with virtual references node workaround
                if (!string.IsNullOrEmpty(projectItem.Name) &&
                    projectItem.Name.Equals(REFERENCES_NODE, StringComparison.OrdinalIgnoreCase) &&
                    (string.Compare(projectItemKind, Constants.vsProjectItemKindVirtualFolder, StringComparison.OrdinalIgnoreCase) == 0))
                {
                    continue;
                }

                if ((string.Compare(projectItemKind, Constants.vsProjectItemKindPhysicalFile, StringComparison.OrdinalIgnoreCase) == 0) ||
                    (string.Compare(projectItemKind, Constants.vsProjectItemKindSolutionItems, StringComparison.OrdinalIgnoreCase) == 0))
                {
                    if (!parentSubTypeSet)
                    {
                        parentSubTypeSet = true;

                        if (parentItem != null)
                        {
                            parentSubType = _fileTypeResolver.GetSubType(parentItem, languageSet, isWebProject);
                        }
                    }

                    var itemSubType = _fileTypeResolver.GetSubType(projectItem, languageSet, isWebProject);

                    // Check if this is a code file
                    var add = !flags.HasFlag(ProcessorFlags.IncludeCodeFilesOnly) || _fileTypeResolver.IsCodeSubType(itemSubType);

                    // Check for .Designer file
                    if (add &&
                        !flags.HasFlag(ProcessorFlags.IncludeDesignerFiles) &&
                        _fileTypeResolver.IsDesignerItem(projectItem, itemSubType, languageSet, isWebProject))
                    {
                        add = false;
                    }

                    // Used to collect skipped files here as well... something to keep an eye out out for
                    if (add)
                    {
                        var fileName = projectItem.get_FileNames(1);
                        if (string.IsNullOrEmpty(fileName))
                        {
                            add = false;
                        }

                        if (add)
                        {
                            // Try getting a misc/simple subtype for unknown and solution projects
                            if ((languageSet?.Type == LanguageType.Unknown) && (itemSubType == FileSubType.None))
                            {
                                itemSubType = _fileTypeResolver.GetExtensionSubType(projectItem, languageSet, isWebProject);
                            }

                            if (string.IsNullOrEmpty(projectName))
                            {
                                projectName = projectItem.ContainingProject?.Name;
                            }

                            var itemModel = new FileModel
                            {
                                ProjectItem       = projectItem,
                                FileName          = projectItem.Name,
                                ParentProjectItem = parentItem,
                                ParentName        = parentName,
                                ParentSubType     = parentSubType,
                                ItemSubType       = itemSubType,
                                FileNameWithPath  = fileName,
                                ProjectName       = projectName
                            };

                            if (flags.HasFlag(ProcessorFlags.IncludeFileCodeModel))
                            {
                                var codeMembers = _fileProcessor.GetMembers(projectItem, flags, filter);
                                if ((codeMembers != null) && (codeMembers.Members != null))
                                {
                                    itemModel.Members.AddRange(codeMembers.Members);
                                }
                            }

                            model.Add(itemModel);
                        }
                    }

                    ProjectItems currentProjectItems = projectItem.ProjectItems;
                    if ((currentProjectItems != null) && (currentProjectItems.Count > 0))
                    {
                        ProcessProjectItems(
                            model, flags, filter, languageSet,
                            currentProjectItems, false, ref isRoot, projectItem, parentName);
                    }
                }
                else                 // projectItemKind
                {
                    if ((string.Compare(projectItemKind, Constants.vsProjectItemKindPhysicalFolder, StringComparison.OrdinalIgnoreCase) == 0) ||
                        (string.Compare(projectItemKind, Constants.vsProjectItemKindVirtualFolder, StringComparison.OrdinalIgnoreCase) == 0))
                    {
                        ProjectItems currentProjectItems = projectItem.ProjectItems;
                        if ((currentProjectItems != null) && (currentProjectItems.Count > 0))
                        {
                            ProcessProjectItems(
                                model, flags, filter, languageSet,
                                currentProjectItems, isWebProject, ref isRoot, projectItem, parentName + projectItem.Name);
                        }
                    }
                }
            }             // foreach (projectItem)
        }
Exemplo n.º 6
0
        /// <summary>
        /// Creates code model element.
        /// </summary>
        private void AddCodeElement(ProjectItem item, CodeElement parentElement, CodeElement element, List <DPackFileCodeModel> model, ProcessorFlags flags,
                                    LanguageSettings languageSet, ICollection <vsCMElement> dteFilter, CodeModelFilterFlags filter)
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            EditPoint editPoint;

            // Line number retrieval uses EditPoints, which is expensive to process
            try
            {
                // Not all elements support header part
                TextPoint startPoint;
                if ((element.Kind == vsCMElement.vsCMElementClass) ||
                    (element.Kind == vsCMElement.vsCMElementModule) ||
                    (element.Kind == vsCMElement.vsCMElementInterface) ||
                    (element.Kind == vsCMElement.vsCMElementStruct) ||
                    (element.Kind == vsCMElement.vsCMElementEnum) ||
                    (element.Kind == vsCMElement.vsCMElementFunction))
                {
                    startPoint = element.GetStartPoint(vsCMPart.vsCMPartHeader);
                }
                else
                {
                    startPoint = element.StartPoint;
                }

                if (startPoint == null)
                {
                    _log.LogMessage($"{element.Name} element's of {element.Kind} kind StartPoint cannot be determined");
                    return;
                }

                // Check if this code model element belongs to the current project item
                if (element.ProjectItem != null)
                {
                    var elementItem = element.ProjectItem;
                    if ((item != null) && (item != elementItem))
                    {
                        string itemFileName = item.get_FileNames(1);
                        string epiFileName  = elementItem.get_FileNames(1);

                        if (string.IsNullOrEmpty(itemFileName) ||
                            string.IsNullOrEmpty(epiFileName) ||
                            (string.Compare(itemFileName, epiFileName, StringComparison.OrdinalIgnoreCase) != 0))
                        {
                            _log.LogMessage($"Project item mismatch: '{item.Name}' expected but '{elementItem.Name}' found instead - {element.Name}");
                            return;
                        }
                        else
                        {
                            // This is a work around for project item reference change where essentially new reference
                            // still points at the same file but reference wise these two are no longer equal
                            item = elementItem;
                        }
                    }
                }

                editPoint = startPoint.CreateEditPoint();
            }
            catch (Exception ex)
            {
                // Swallow C++ exception as some invalid code model functions raise it sometimes
                if (languageSet?.Language != CodeModelLanguageConstants.vsCMLanguageVC)
                {
                    _log.LogMessage($"Error adding code member: {element.Name}", ex);
                }

                return;
            }

            var line = editPoint.Line;

            // Decide whether the element is to be filtered out or not
            bool add;

            if (dteFilter?.Count == 0)
            {
                add = true;
            }
            else
            {
                add = dteFilter.Contains(element.Kind);
                if (!add)
                {
                    // TODO: resurrect next statement if need be - used to treat read-only fields as properties
                    //if (dteFilter.Contains(vsCMElement.vsCMElementProperty) && (element.Kind == vsCMElement.vsCMElementVariable))
                    //{
                    //	var varElt = (CodeVariable2)element;
                    //	if (varElt.ConstKind == vsCMConstKind.vsCMConstKindReadOnly)
                    //		add = true;
                    //}
                }
            }

            if (add)
            {
                GetConstructorDestructorInfo(languageSet, parentElement, element, out bool constructor, out bool destructor);

                if ((filter != CodeModelFilterFlags.Constructors) ||
                    (filter.HasFlag(CodeModelFilterFlags.Constructors) && (constructor || destructor)))
                {
                    var    name = element.Name;
                    string parentFullName;
                    var    fullName = flags.HasFlag(ProcessorFlags.IncludeMemeberFullName) ? element.FullName : string.Empty;
                    var    code     = string.Empty;

                    // Setup element's full name information
                    if (string.IsNullOrEmpty(name))
                    {
                        name = UNNAMED_NAME;
                    }
                    if (parentElement == null)
                    {
                        if (!flags.HasFlag(ProcessorFlags.IncludeMemeberFullName) && (languageSet != null) && languageSet.ParentlessFullName)
                        {
                            parentFullName = element.FullName;
                        }
                        else
                        {
                            parentFullName = name;
                        }
                    }
                    else
                    if ((parentElement.Kind == vsCMElement.vsCMElementClass) ||
                        (parentElement.Kind == vsCMElement.vsCMElementModule) ||
                        (parentElement.Kind == vsCMElement.vsCMElementInterface) ||
                        (parentElement.Kind == vsCMElement.vsCMElementStruct))
                    {
                        parentFullName = parentElement.Name + "." + name;
                    }
                    else
                    {
                        parentFullName = name;
                    }

                    // Check for duplicate names
                    if ((languageSet != null) && languageSet.CheckDuplicateNames)
                    {
                        foreach (var modelItem in model)
                        {
                            if ((modelItem.Line == line) &&
                                (modelItem.CodeModelElementKind == (int)element.Kind) &&
                                (modelItem.ParentFullName == parentFullName))
                            {
                                // Duplicate found
                                add = false;
                                break;
                            }
                        }
                    }

                    if (add)
                    {
                        // Setup element's first code line information
                        if (editPoint != null)
                        {
                            int lineLength = editPoint.LineLength - editPoint.LineCharOffset + 1;
                            if (lineLength > 1)
                            {
                                code = editPoint.GetText(lineLength).TrimStart(' ', '\t');
                            }
                        }

                        try
                        {
                            var returnTypeName = constructor || destructor || (element == null) ? string.Empty : GetElementReturnTypeName(element);
                            var xmlDoc         = flags.HasFlag(ProcessorFlags.IncludeMemberXmlDoc) ? GetXmlDoc(element, languageSet) : string.Empty;

                            char?genericSuffix = null;
                            if ((languageSet != null) && languageSet.SupportsGenerics)
                            {
                                var suffix = _shellCodeModelService.GetGenericsSuffix(element);

                                if (!string.IsNullOrEmpty(suffix))
                                {
                                    name           = name + suffix;
                                    parentFullName = parentFullName + suffix;
                                    genericSuffix  = suffix[0];
                                }
                            }

                            var modelItem = new DPackFileCodeModel
                            {
                                ProjectItem          = element.ProjectItem,
                                Name                 = name,
                                FullName             = fullName,
                                ParentFullName       = parentFullName,
                                CodeModelElementKind = (int)element.Kind,
                                ElementKind          = _shellCodeModelService.GetElementKind(element),
                                ElementModifier      = _shellCodeModelService.GetElementModifier(element),
                                IsConstant           = _shellCodeModelService.IsConstant(element),
                                IsStatic             = _shellCodeModelService.IsStatic(element),
                                SupportsGenerics     = languageSet.SupportsGenerics,
                                GenericsSuffix       = _shellCodeModelService.GetGenericsSuffix(element),
                                Line                 = line,
                                Code                 = code,
                                ReturnTypeName       = returnTypeName,
                                XmlDoc               = xmlDoc
                            };

                            model.Add(modelItem);
                        }
                        catch (COMException ex)
                        {
                            _log.LogMessage($"Ignored COM code model error for {name}", ex);
                        }
                    }     // if (add)
                }         // if (memberFilter)
            }             // if (add)
        }
Exemplo n.º 7
0
        /// <summary>
        /// Processes individual project.
        /// </summary>
        /// <returns>Whether project's been processed or not.</returns>
        private bool ProcessProject(Project project, ICollection <ProjectModel> model, ProcessorFlags flags, CodeModelFilterFlags filter)
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            var process  = true;
            var language = string.Empty;

            // Safety check & language retrieval
            try
            {
                var items = project.ProjectItems;
                if ((items != null) && (items.Count > 0))
                {
                    if (_shellProjectService.IsCodeModelProject(project))
                    {
                        language = _shellProjectService.GetProjectLanguage(project);
                        if (string.IsNullOrEmpty(language))
                        {
                            process = false;
                        }
                    }
                    else
                    {
                        language = _shellProjectService.GetNoCodeModelProjectLanguage(project);
                        if (string.IsNullOrEmpty(language))
                        {
                            process = false;
                        }
                    }
                }
            }
            catch (NotImplementedException)             // This is an acceptable condition - keep on going
            {
                process = false;
                _log.LogMessage($"Project '{project?.Name}' doesn't implement code model");
            }
            catch (Exception ex)             // But this is a legit problem - keep on going anyways
            {
                process = false;
                _log.LogMessage("Failed to retrieve project code model / language", ex);
            }

            string projectFullName = string.Empty;

            if (process)
            {
                _shellProjectService.GetProjectPath(project, out string projectPath, out projectFullName);
                if ((string.IsNullOrEmpty(projectPath) || string.IsNullOrEmpty(projectFullName)) && _shellProjectService.IsProject(project))
                {
                    process = false;
                    _log.LogMessage($"Project '{project?.Name}' path is not available");
                }
            }

            if (process)
            {
                var projectModel = new ProjectModel
                {
                    Project      = project,
                    Name         = project.Name,
                    FriendlyName = _shellProjectService.GetFriendlyProjectName(project),
                    FileName     = projectFullName,
                    Language     = _languageService.GetLanguage(language)
                };

                if (flags.HasFlag(ProcessorFlags.IncludeFiles))
                {
                    var files = _projectProcessor.GetFiles(project, flags, filter);
                    if (files != null)
                    {
                        projectModel.Files.AddRange(files);
                        files.ForEach(f => f.Project = projectModel);
                    }
                }

                model.Add(projectModel);
            }

            return(process);
        }
Exemplo n.º 8
0
        /// <summary>
        /// Returns solution projects.
        /// </summary>
        private void GetProjectsInternal(SolutionModel model, ProcessorFlags flags, CodeModelFilterFlags filter)
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            _log.LogMessage("Collecting solution projects", LOG_CATEGORY);

            var dte             = _shellProjectService.GetDTE() as DTE;
            var serviceProvider = new Microsoft.VisualStudio.Shell.ServiceProvider(dte as Microsoft.VisualStudio.OLE.Interop.IServiceProvider);
            var solutionService = serviceProvider.GetService <IVsSolution, SVsSolution>(false);

            Guid guid = Guid.Empty;

            if (solutionService.GetProjectEnum((uint)__VSENUMPROJFLAGS.EPF_LOADEDINSOLUTION, ref guid, out IEnumHierarchies enumHierarchies) != VSConstants.S_OK)
            {
                return;
            }

            IVsHierarchy[] hierarchy = new IVsHierarchy[1];
            List <Project> projects  = new List <Project>();

            while ((enumHierarchies.Next((uint)hierarchy.Length, hierarchy, out uint fetched) == VSConstants.S_OK) && (fetched == hierarchy.Length))
            {
                if ((hierarchy.Length > 0) && (hierarchy[0] != null))
                {
                    IVsHierarchy projectHierarchy = hierarchy[0];

                    if ((projectHierarchy.GetProperty((uint)VSConstants.VSITEMID.Root, (int)__VSHPROPID.VSHPROPID_ExtObject, out object project) == VSConstants.S_OK) &&
                        (project is Project dteProject) &&
                        _shellProjectService.IsProject(project))
                    {
                        projects.Add(dteProject);
                    }
                }
            }

            _log.LogMessage("Resolving solution name", LOG_CATEGORY);

            var solution = dte.Solution?.FileName;

            if (!string.IsNullOrEmpty(solution))
            {
                solution = Path.GetFileNameWithoutExtension(solution);
            }
            model.SolutionName = solution;

            _log.LogMessage($"Processing {projects.Count} collected solution projects", LOG_CATEGORY);

            foreach (Project project in projects)
            {
                if (_shellProjectService.IsProjectLoadDeferred(project, out _))
                {
                    continue;
                }

                if (ProcessProject(project, model.Projects, flags, filter))
                {
                    ProcessProjectRecursively(project, model.Projects, flags, filter);
                }
            }

            model.Files = model.Projects.SelectMany(p => p.Files).ToList();

            if (flags.HasFlag(ProcessorFlags.GroupLinkedFiles))
            {
                // Get all grouped, ie duplicate, files, keep the first code file and remove the rest
                var groupedFiles = model.Files.GroupBy(f => f.FileNameWithPath).Where(g => g.Count() > 1).Select(g => g);
                foreach (var group in groupedFiles)
                {
                    var file = group.FirstOrDefault(f => f.Project.Language.SupportsCompileBuildAction && _shellProjectService.CompileBuildAction(f.ProjectItem));
                    if (file != null)
                    {
                        group.ForEach(f =>
                        {
                            if (f != file)
                            {
                                model.Files.Remove(f);
                                f.Project.Files.Remove(f);
                                AddProjectName(file, f.ProjectName);
                            }
                        });
                    }
                }
            }

            _log.LogMessage($"Processed {model.Projects.Count} qualified solution projects", LOG_CATEGORY);
        }