public void MultiValueDictionary_Add_Set()
        {
            var mvd = MultiValueDictionary <int, int> .Create <HashSet <int> >();

            mvd.Add(5, 42);
            mvd.Add(5, 42);
            mvd.Add(42, 42);

            Assert.AreEqual(2, mvd.Keys.Count);
            Assert.AreEqual(1, mvd[5].Count);
        }
        public void MultiValueDictionary_Add_Set()
        {
            var mvd = MultiValueDictionary <int, int> .Create <HashSet <int> >();

            mvd.Add(5, 42);
            mvd.Add(5, 42);
            mvd.Add(42, 42);

            mvd.Keys.Should().HaveCount(2);
            mvd[5].Should().HaveCount(1);
        }
        public override void Initialize(AnalysisContext context)
        {
            context.RegisterCompilationStartAction(
                analysisContext =>
            {
                var disposeMethod = DisposableNotDisposed.GetDisposeMethod(analysisContext.Compilation);
                if (disposeMethod == null)
                {
                    return;
                }

                var disposeMethodsCalledFromDispose = MultiValueDictionary <INamedTypeSymbol, IMethodSymbol> .Create <HashSet <IMethodSymbol> >();
                var implementingDisposeMethods      = ImmutableHashSet <IMethodSymbol> .Empty;
                var allDisposeMethods = ImmutableHashSet <IMethodSymbol> .Empty;

                analysisContext.RegisterSymbolAction(c =>
                                                     CollectDisposeMethods(c, disposeMethod, ref allDisposeMethods, ref implementingDisposeMethods),
                                                     SymbolKind.Method);

                analysisContext.RegisterCodeBlockStartAction <SyntaxKind>(
                    cbc =>
                {
                    var methodDeclaration = cbc.CodeBlock as MethodDeclarationSyntax;
                    if (methodDeclaration == null ||
                        methodDeclaration.Identifier.ValueText != DisposeMethodName)
                    {
                        return;
                    }

                    var declaredMethodSymbol = cbc.SemanticModel.GetDeclaredSymbol(methodDeclaration);
                    if (declaredMethodSymbol == null ||
                        !MethodIsDisposeImplementation(declaredMethodSymbol, disposeMethod))
                    {
                        return;
                    }

                    var disposableType = declaredMethodSymbol.ContainingType;
                    cbc.RegisterSyntaxNodeAction(
                        c => CollectDisposeMethodsCalledFromDispose((InvocationExpressionSyntax)c.Node,
                                                                    c.SemanticModel, disposableType, disposeMethodsCalledFromDispose),
                        SyntaxKind.InvocationExpression);
                });

                analysisContext.RegisterCompilationEndAction(
                    c =>
                    ReportDisposeMethods(allDisposeMethods, implementingDisposeMethods,
                                         disposeMethodsCalledFromDispose, c));
            });
        }
        protected override void Initialize(SonarAnalysisContext context)
        {
            context.RegisterCompilationStartAction(analysisContext =>
            {
                if (analysisContext.Compilation.IsTest())
                {
                    return;
                }

                var fieldsByNamedType = MultiValueDictionary <INamedTypeSymbol, IFieldSymbol> .Create <HashSet <IFieldSymbol> >();
                var fieldsAssigned    = ImmutableHashSet <IFieldSymbol> .Empty;

                analysisContext.RegisterSymbolAction(c =>
                {
                    var namedTypeSymbol = (INamedTypeSymbol)c.Symbol;
                    if (!namedTypeSymbol.IsClass() ||
                        namedTypeSymbol.Implements(KnownType.System_IDisposable))
                    {
                        return;
                    }

                    var disposableFields = namedTypeSymbol.GetMembers()
                                           .OfType <IFieldSymbol>()
                                           .Where(IsNonStaticNonPublicDisposableField)
                                           .ToImmutableHashSet();

                    fieldsByNamedType.AddRangeWithKey(namedTypeSymbol, disposableFields);
                }, SymbolKind.NamedType);


                analysisContext.RegisterSyntaxNodeAction(c =>
                {
                    var assignment  = (AssignmentExpressionSyntax)c.Node;
                    var expression  = assignment.Right;
                    var fieldSymbol = c.SemanticModel.GetSymbolInfo(assignment.Left).Symbol as IFieldSymbol;

                    fieldsAssigned = AddFieldIfNeeded(fieldSymbol, expression, fieldsAssigned);
                }, SyntaxKind.SimpleAssignmentExpression);

                analysisContext.RegisterSyntaxNodeAction(c =>
                {
                    var field = (FieldDeclarationSyntax)c.Node;

                    foreach (var variableDeclaratorSyntax in field.Declaration.Variables
                             .Where(declaratorSyntax => declaratorSyntax.Initializer != null))
                    {
                        var fieldSymbol = c.SemanticModel.GetDeclaredSymbol(variableDeclaratorSyntax) as IFieldSymbol;

                        fieldsAssigned = AddFieldIfNeeded(fieldSymbol, variableDeclaratorSyntax.Initializer.Value,
                                                          fieldsAssigned);
                    }
                }, SyntaxKind.FieldDeclaration);

                analysisContext.RegisterCompilationEndAction(c =>
                {
                    foreach (var kv in fieldsByNamedType)
                    {
                        foreach (var classSyntax in kv.Key.DeclaringSyntaxReferences
                                 .Select(declaringSyntaxReference => declaringSyntaxReference.GetSyntax())
                                 .OfType <ClassDeclarationSyntax>())
                        {
                            var assignedFields = kv.Value.Intersect(fieldsAssigned).ToList();

                            if (!assignedFields.Any())
                            {
                                continue;
                            }
                            var variableNames = string.Join(", ",
                                                            assignedFields.Select(symbol => $"\"{symbol.Name}\"").OrderBy(s => s));

                            c.ReportDiagnosticIfNonGenerated(
                                Diagnostic.Create(Rule, classSyntax.Identifier.GetLocation(), variableNames),
                                c.Compilation);
                        }
                    }
                });
            });
        }
Exemple #5
0
        public TerrainOverlayNetwork CompileTerrainOverlayNetwork(double agentRadius)
        {
            if (terrainOverlayNetworkCache.TryGetValue(agentRadius, out var existingTerrainOverlayNetwork))
            {
                return(existingTerrainOverlayNetwork);
            }

            //         Console.WriteLine($"Compiling Terrain Overlay Network for Agent Radius {agentRadius}.");
            //----------------------------------------------------------------------------------------
            // Sector Node Description => Default Local Geometry View
            //----------------------------------------------------------------------------------------
            var renderedLocalGeometryViewBySectorNodeDescription = localGeometryViewManagerBySectorNodeDescription.Map(
                (k, v) => v.GetErodedView(agentRadius * k.WorldToLocalScalingFactor));

            var defaultLocalGeometryViewBySectorNodeDescription = renderedLocalGeometryViewBySectorNodeDescription.Map(
                (k, v) => true || v.IsPunchedLandEvaluated ? v : v.Preview);

            var landPolyNodesByDefaultLocalGeometryView = defaultLocalGeometryViewBySectorNodeDescription.Values.Distinct().ToDictionary(
                lgv => lgv,
                lgv => lgv.PunchedLand.GetLandNodes());

            var terrainNodesBySectorNodeDescription = defaultLocalGeometryViewBySectorNodeDescription.Map(
                (k, v) => landPolyNodesByDefaultLocalGeometryView[v].Map(pn => new TerrainOverlayNetworkNode(k, v, pn)));

            var terrainNodesBySectorNodeDescriptionAndPolyNode = terrainNodesBySectorNodeDescription.Values.SelectMany(tns => tns).ToDictionary(
                tn => (tn.SectorNodeDescription, tn.LandPolyNode));

            //----------------------------------------------------------------------------------------
            // Edge Lookups
            //----------------------------------------------------------------------------------------
            var edgesBySource      = edgeDescriptions.ToLookup(ed => ed.Source);
            var edgesByDestination = edgeDescriptions.ToLookup(ed => ed.Destination);
            var edgesByEndpoints   = MultiValueDictionary <SectorNodeDescription, SectorEdgeDescription> .Create(() => new HashSet <SectorEdgeDescription>());

            foreach (var(k, edges) in edgesBySource)
            {
                foreach (var edge in edges)
                {
                    edgesByEndpoints.Add(k, edge);
                }
            }
            foreach (var(k, edges) in edgesByDestination)
            {
                foreach (var edge in edges)
                {
                    edgesByEndpoints.Add(k, edge);
                }
            }

            //----------------------------------------------------------------------------------------
            // Build and Initialize Terrain Overlay Network
            //----------------------------------------------------------------------------------------
            var terrainOverlayNetwork = new TerrainOverlayNetwork(
                agentRadius,
                defaultLocalGeometryViewBySectorNodeDescription,
                terrainNodesBySectorNodeDescription,
                landPolyNodesByDefaultLocalGeometryView,
                terrainNodesBySectorNodeDescriptionAndPolyNode,
                edgeDescriptions,
                edgesBySource,
                edgesByDestination,
                edgesByEndpoints);

            terrainOverlayNetwork.Initialize();
            return(terrainOverlayNetworkCache[agentRadius] = terrainOverlayNetwork);
        }
Exemple #6
0
        private static MultiValueDictionary <TerrainOverlayNetworkNode, IntLineSegment2> FindVisibleCrossoverSegmentsByNeighborAndClearLocalAt(
            IDebugCanvas canvas,
            TerrainOverlayNetworkNode terrainNode,
            VisibilityPolygon visibilityPolygon,
            IntVector2 visibilityPolygonOrigin,
            HashSet <TerrainOverlayNetworkNode> visited = null)
        {
            var visibleCrossoverSegmentsByNeighbor = MultiValueDictionary <TerrainOverlayNetworkNode, IntLineSegment2> .Create(() => new HashSet <IntLineSegment2>());

            foreach (var outboundEdgeGroup in terrainNode.OutboundEdgeGroups)
            {
                var otherTerrainNode = outboundEdgeGroup.Key;
                if (visited?.Contains(otherTerrainNode) ?? false)
                {
                    continue;
                }

                foreach (var outboundEdge in outboundEdgeGroup.Value)
                {
                    var ranges = visibilityPolygon.Get();

                    (IntLineSegment2, bool) FlipMaybeSorta(IntLineSegment2 x) =>
                    GeometryOperations.Clockness(visibilityPolygonOrigin, x.First, x.Second) == Clockness.CounterClockwise
                     ? (new IntLineSegment2(x.Second, x.First), true)
                     : (x, false);

                    var(localCrossoverSegment, lcsFlipped)  = FlipMaybeSorta(outboundEdge.EdgeJob.EdgeDescription.SourceSegment);
                    var(remoteCrossoverSegment, rcsFlipped) = FlipMaybeSorta(outboundEdge.EdgeJob.EdgeDescription.DestinationSegment);

                    // todo: clamp visibleStartT, visibleEndT to account for agent radius eroding crossover segmetmentnt
                    var rangeIndexIntervals    = visibilityPolygon.RangeStab(localCrossoverSegment);
                    var locallyClearedSegments = new List <IntLineSegment2>();
                    foreach (var(startIndexInclusive, endIndexInclusive) in rangeIndexIntervals)
                    {
                        for (var i = startIndexInclusive; i <= endIndexInclusive; i++)
                        {
                            if (ranges[i].Id == VisibilityPolygon.RANGE_ID_INFINITELY_FAR || ranges[i].Id == VisibilityPolygon.RANGE_ID_INFINITESIMALLY_NEAR)
                            {
                                continue;
                            }

                            var seg = ranges[i].Segment;

                            var rstart = DoubleVector2.FromRadiusAngle(100, ranges[i].ThetaStart) * 100;
                            var rend   = DoubleVector2.FromRadiusAngle(100, ranges[i].ThetaEnd) * 100;

                            double visibleStartT, visibleEndT;
                            if (!GeometryOperations.TryFindNonoverlappingLineLineIntersectionT(localCrossoverSegment.First.ToDoubleVector2(), localCrossoverSegment.Second.ToDoubleVector2(), visibilityPolygonOrigin.ToDoubleVector2(), visibilityPolygonOrigin.ToDoubleVector2() + rstart, out visibleStartT) ||
                                !GeometryOperations.TryFindNonoverlappingLineLineIntersectionT(localCrossoverSegment.First.ToDoubleVector2(), localCrossoverSegment.Second.ToDoubleVector2(), visibilityPolygonOrigin.ToDoubleVector2(), visibilityPolygonOrigin.ToDoubleVector2() + rend, out visibleEndT))
                            {
                                // wtf?
                                Console.WriteLine("???");
                                continue;
                            }

                            // Todo: I don't actually understand why visibleEndT > 1 is a thing?
                            // t values are for parameterization of crossover line segment, so must be within [0, 1]
                            if ((visibleStartT < 0 && visibleEndT < 0) || (visibleStartT > 1 && visibleEndT > 1))
                            {
                                continue;
                            }
                            visibleStartT = Math.Min(1.0, Math.Max(0.0, visibleStartT));
                            visibleEndT   = Math.Min(1.0, Math.Max(0.0, visibleEndT));

                            if (visibilityPolygon.SegmentComparer.Compare(localCrossoverSegment, seg) < 0)
                            {
                                var localVisibleStart = localCrossoverSegment.PointAt(visibleStartT).LossyToIntVector2();
                                var localVisibleEnd   = localCrossoverSegment.PointAt(visibleEndT).LossyToIntVector2();

                                var remoteVisibleStart = remoteCrossoverSegment.PointAt(lcsFlipped == rcsFlipped ? visibleStartT : 1.0 - visibleStartT).LossyToIntVector2();
                                var remoteVisibleEnd   = remoteCrossoverSegment.PointAt(lcsFlipped == rcsFlipped ? visibleEndT : 1.0 - visibleEndT).LossyToIntVector2();

                                if (localVisibleStart == localVisibleEnd)
                                {
                                    continue;
                                }
                                if (remoteVisibleStart == remoteVisibleEnd)
                                {
                                    continue;
                                }

                                var locallyClearedSegment = new IntLineSegment2(localVisibleStart, localVisibleEnd);
                                locallyClearedSegments.Add(locallyClearedSegment);

                                visibleCrossoverSegmentsByNeighbor.Add(otherTerrainNode, new IntLineSegment2(remoteVisibleStart, remoteVisibleEnd));
                            }
                        }
                    }
                    foreach (var locallyClearedSegment in locallyClearedSegments)
                    {
                        visibilityPolygon.ClearBefore(locallyClearedSegment);
                    }
                }
            }
            return(visibleCrossoverSegmentsByNeighbor);
        }