예제 #1
0
        public async Task <ProgramComposition> ProcessAsync(ProgramComposition composition, ProjectScriptInfo config)
        {
            _externallyReferencedTypes.Clear();
            var usageAnalyzer = new UsageAnalyzer();
            var typeUsages    = await usageAnalyzer.FindUsagesAsync(composition, config);

            foreach (var typeUsage in typeUsages)
            {
                foreach (var part in typeUsage.Usage)
                {
                    foreach (var location in part.Locations)
                    {
                        var node = composition.RootNode.FindNode(location.Location.SourceSpan);
                        if (IsInProgram(node))
                        {
                            _externallyReferencedTypes.Add(typeUsage.FullName);
                        }
                    }
                }
            }

            var root = composition.RootNode;

            root = Visit(root);
            return(await composition.WithNewDocumentRootAsync(root));
        }
예제 #2
0
        public async Task <ProgramComposition> ProcessAsync([NotNull] ProgramComposition composition, [NotNull] ProjectScriptInfo config)
        {
            if (composition == null)
            {
                throw new ArgumentNullException(nameof(composition));
            }
            if (config == null)
            {
                throw new ArgumentNullException(nameof(config));
            }
            var analyzer = new UsageAnalyzer();

            while (true)
            {
                var symbolDefinitions = await analyzer.FindUsagesAsync(composition, config);

                var symbol = symbolDefinitions.FirstOrDefault(s => !s.IsProtected && s.SyntaxNode.IsTypeDeclaration() && HasNoUsage(s));
                if (symbol == null)
                {
                    break;
                }

                var rootNode = RemoveDefinition(composition.RootNode, symbol);
                composition = await composition.WithNewDocumentRootAsync(rootNode);
            }

            return(composition);
        }
예제 #3
0
        public async Task <ProgramComposition> ProcessAsync(ProgramComposition composition, MDKProjectProperties config)
        {
            var newDocument = await Simplifier.ReduceAsync(composition.Document).ConfigureAwait(false);

            composition = await(composition.WithDocumentAsync(newDocument).ConfigureAwait(false));

            _externallyReferencedMembers.Clear();
            var usageAnalyzer = new UsageAnalyzer();
            var typeUsages    = await usageAnalyzer.FindUsagesAsync(composition, config);

            foreach (var typeUsage in typeUsages)
            {
                foreach (var part in typeUsage.Usage)
                {
                    foreach (var location in part.Locations)
                    {
                        var node = composition.RootNode.FindNode(location.Location.SourceSpan);
                        if (!IsInProgram(node))
                        {
                            _externallyReferencedMembers.Add(typeUsage.FullName);
                        }
                    }
                }
            }

            var root = composition.RootNode;

            root = Visit(root);
            return(await composition.WithNewDocumentRootAsync(root));
        }
예제 #4
0
        public async Task <ProgramComposition> ProcessAsync([NotNull] ProgramComposition composition, [NotNull] ProjectScriptInfo config)
        {
            if (composition == null)
            {
                throw new ArgumentNullException(nameof(composition));
            }
            if (config == null)
            {
                throw new ArgumentNullException(nameof(config));
            }
            var nodes             = new Dictionary <ISymbol, Node>();
            var analyzer          = new UsageAnalyzer();
            var symbolDefinitions = await analyzer.FindUsagesAsync(composition, config);

            var symbolLookup = symbolDefinitions.GroupBy(d => d.Symbol).ToDictionary(g => g.Key, g => g.ToList());
            var rootNode     = composition.RootNode;

            foreach (var definition in symbolDefinitions)
            {
                if (!(definition.Symbol is ITypeSymbol typeSymbol))
                {
                    continue;
                }
                if (typeSymbol.TypeKind == TypeKind.TypeParameter)
                {
                    continue;
                }

                if (!nodes.TryGetValue(definition.Symbol, out var node))
                {
                    nodes[definition.Symbol] = node = new Node(definition);
                }
                else
                {
                    node.Definitions.Add(definition);
                }

                foreach (var usage in definition.Usage)
                {
                    foreach (var location in usage.Locations)
                    {
                        var enclosingSymbol = await FindTypeSymbolAsync(rootNode, location);

                        var enclosingSymbolDefinitions = symbolLookup[enclosingSymbol];
                        if (!nodes.TryGetValue(enclosingSymbol, out var referencingNode))
                        {
                            nodes[enclosingSymbol] = referencingNode = new Node(enclosingSymbolDefinitions);
                        }
                        if (node != referencingNode)
                        {
                            referencingNode.References.Add(node);
                        }
                    }
                }
            }

            var program = symbolDefinitions.FirstOrDefault(d => d.FullName == "Program");

            if (program == null || !nodes.TryGetValue(program.Symbol, out var programNode))
            {
                throw new BuildException(string.Format(Text.TypeTrimmer_ProcessAsync_NoEntryPoint, composition.Document.Project.FilePath));
            }

            var usedNodes    = new List <Node>();
            var queue        = new Queue <Node>();
            var visitedNodes = new HashSet <Node>();

            queue.Enqueue(programNode);
            while (queue.Count > 0)
            {
                var node = queue.Dequeue();
                if (!visitedNodes.Add(node))
                {
                    continue;
                }
                usedNodes.Add(node);
                foreach (var reference in node.References)
                {
                    queue.Enqueue(reference);
                }
            }

            var usedSymbolDefinitions   = usedNodes.SelectMany(n => n.Definitions).ToImmutableHashSet();
            var unusedSymbolDefinitions = symbolDefinitions.Where(definition => IsEligibleForRemoval(definition) && !usedSymbolDefinitions.Contains(definition)).ToList();
            var nodesToRemove           = unusedSymbolDefinitions.Select(definition => definition.FullName).ToImmutableHashSet();

            var walker = new RemovalWalker(nodesToRemove);

            rootNode = walker.Visit(rootNode);
            foreach (var symbol in unusedSymbolDefinitions)
            {
                rootNode = RemoveDefinition(rootNode, symbol);
            }

            return(await composition.WithNewDocumentRootAsync(rootNode));
        }
 static DataController()
 {
     usageAnalyzer = new UsageAnalyzer(GetUsageSettings(), UsageType.Display);
 }