public void ThreeItems() { var dict = new SmallDictionary<int, string>(); dict[2] = "abc"; dict[5] = "def"; dict[11] = "third"; Assert.AreEqual(3, dict.Count); Assert.AreEqual("abc", dict[2]); Assert.AreEqual("def", dict[5]); Assert.AreEqual("third", dict[11]); string output; Assert.IsFalse(dict.TryGetValue(3, out output)); Assert.IsNull(output); Assert.IsTrue(dict.TryGetValue(2, out output)); Assert.AreEqual("abc", output); Assert.IsTrue(dict.TryGetValue(5, out output)); Assert.AreEqual("def", output); Assert.IsTrue(dict.TryGetValue(11, out output)); Assert.AreEqual("third", output); Assert.IsFalse(dict.ContainsKey(3)); Assert.IsTrue(dict.ContainsKey(2)); Assert.IsTrue(dict.ContainsKey(5)); Assert.IsTrue(dict.ContainsKey(11)); }
public override void VisitFinallyClause(FinallyClauseSyntax node) { // NOTE: We're going to cheat a bit - we know that the block is definitely going // to get a map entry, so we don't need to worry about the WithAdditionalFlags // binder being dropped. That is, there's no point in adding the WithAdditionalFlags // binder to the map ourselves and having VisitBlock unconditionally overwrite it. // If this finally block is nested inside a catch block, we need to use a distinct // binder flag so that we can detect the nesting order for error CS074: A throw // statement with no arguments is not allowed in a finally clause that is nested inside // the nearest enclosing catch clause. var additionalFlags = BinderFlags.InFinallyBlock; if (_enclosing.Flags.Includes(BinderFlags.InCatchBlock)) { additionalFlags |= BinderFlags.InNestedFinallyBlock; } Visit(node.Block, _enclosing.WithAdditionalFlags(additionalFlags)); Binder finallyBinder; Debug.Assert(_map.TryGetValue(node.Block, out finallyBinder) && finallyBinder.Flags.Includes(BinderFlags.InFinallyBlock)); }
public void OneItem() { var dict = new SmallDictionary<int, string>(); dict[2] = "abc"; Assert.AreEqual(1, dict.Count); Assert.AreEqual("abc", dict[2]); string output; Assert.IsFalse(dict.TryGetValue(3, out output)); Assert.IsNull(output); Assert.IsTrue(dict.TryGetValue(2, out output)); Assert.AreEqual("abc", output); Assert.IsFalse(dict.ContainsKey(3)); Assert.IsTrue(dict.ContainsKey(2)); }
private void AddIfCaptured(Symbol symbol, SyntaxNode syntax) { Debug.Assert( symbol.Kind == SymbolKind.Local || symbol.Kind == SymbolKind.Parameter || symbol.Kind == SymbolKind.Method); if (_currentClosure == null) { // Can't be captured if we're not in a closure return; } if (symbol is LocalSymbol local && local.IsConst) { // consts aren't captured since they're inlined return; } if (symbol.ContainingSymbol != _currentClosure.OriginalMethodSymbol) { // Restricted types can't be hoisted, so they are not permitted to be captured AddDiagnosticIfRestrictedType(symbol, syntax); // Record the captured variable where it's captured var scope = _currentScope; var closure = _currentClosure; while (closure != null && symbol.ContainingSymbol != closure.OriginalMethodSymbol) { closure.CapturedVariables.Add(symbol); // Also mark captured in enclosing scopes while (scope.ContainingClosureOpt == closure) { scope = scope.Parent; } closure = scope.ContainingClosureOpt; } // Also record where the captured variable lives // No need to record where local functions live: that was recorded // in the Closures list in each scope if (symbol.Kind == SymbolKind.Method) { return; } if (_localToScope.TryGetValue(symbol, out var declScope)) { declScope.DeclaredVariables.Add(symbol); } else { // Parameters and locals from expression tree lambdas // don't get recorded Debug.Assert(_inExpressionTree); } } }
public void TestSmallDict() { var ht = new SmallDictionary <int, int>(); const int elements = 150; for (int i = 0; i < elements; i += 4) { ht.Add(i, i); ht.Add(i - 1, i - 1); ht.Add(i - 2, i - 2); ht.Add(i - 3, i - 3); } Assert.Equal(152, ht.Count()); for (int j = 0; j < 100; j++) { for (int i = 0; i < elements; i += 4) { int v; ht.TryGetValue(i, out v); Assert.Equal(i, v); ht.TryGetValue(i - 1, out v); Assert.Equal(i - 1, v); ht.TryGetValue(i - 2, out v); Assert.Equal(i - 2, v); ht.TryGetValue(i - 3, out v); Assert.Equal(i - 3, v); } } foreach (var p in ht) { Assert.Equal(p.Key, p.Value); } var keys = ht.Keys.ToArray(); var values = ht.Values.ToArray(); for (int i = 0, l = ht.Count(); i < l; i++) { Assert.Equal(keys[i], values[i]); } }
public void TestSmallDict() { var ht = new SmallDictionary<int, int>(); const int elements = 150; for (int i = 0; i < elements; i += 4) { ht.Add(i, i); ht.Add(i - 1, i - 1); ht.Add(i - 2, i - 2); ht.Add(i - 3, i - 3); } Assert.Equal(152, ht.Count()); for (int j = 0; j < 100; j++) { for (int i = 0; i < elements; i += 4) { int v; ht.TryGetValue(i, out v); Assert.Equal(i, v); ht.TryGetValue(i - 1, out v); Assert.Equal(i - 1, v); ht.TryGetValue(i - 2, out v); Assert.Equal(i - 2, v); ht.TryGetValue(i - 3, out v); Assert.Equal(i - 3, v); } } foreach(var p in ht) { Assert.Equal(p.Key, p.Value); } var keys = ht.Keys.ToArray(); var values = ht.Values.ToArray(); for (int i = 0, l = ht.Count(); i < l; i++) { Assert.Equal(keys[i], values[i]); } }
static bool isValueType( TypeParameterSymbol thisTypeParameter, ImmutableArray <TypeParameterConstraintClause> constraintClauses, SmallDictionary <TypeParameterSymbol, bool> isValueTypeMap, ConsList <TypeParameterSymbol> inProgress ) { if (inProgress.ContainsReference(thisTypeParameter)) { return(false); } if (isValueTypeMap.TryGetValue(thisTypeParameter, out bool knownIsValueType)) { return(knownIsValueType); } TypeParameterConstraintClause constraintClause = constraintClauses[ thisTypeParameter.Ordinal ]; bool result = false; if ( (constraintClause.Constraints & TypeParameterConstraintKind.AllValueTypeKinds) != 0 ) { result = true; } else { Symbol container = thisTypeParameter.ContainingSymbol; inProgress = inProgress.Prepend(thisTypeParameter); foreach (TypeWithAnnotations constraintType in constraintClause.ConstraintTypes) { TypeSymbol type = constraintType.IsResolved ? constraintType.Type : constraintType.DefaultType; if ( type is TypeParameterSymbol typeParameter && (object)typeParameter.ContainingSymbol == (object)container ) { if ( isValueType( typeParameter, constraintClauses, isValueTypeMap, inProgress ) ) { result = true; break; } }
private void AddIfCaptured(Symbol symbol) { if (_currentClosure == null) { // Can't be captured if we're not in a closure return; } if (symbol is LocalSymbol local && local.IsConst) { // consts aren't captured since they're inlined return; } if (symbol.ContainingSymbol != _currentClosure.OriginalMethodSymbol) { // Record the captured variable where it's captured var scope = _currentScope; var closure = _currentClosure; while (closure != null && symbol.ContainingSymbol != closure.OriginalMethodSymbol) { closure.CapturedVariables.Add(symbol); // Also mark captured in enclosing scopes while (scope.ContainingClosure == closure) { scope = scope.Parent; } closure = scope.ContainingClosure; } // Also record where the captured variable lives // No need to record where local functions live: that was recorded // in the Closures list in each scope if (symbol.Kind == SymbolKind.Method) { return; } // The 'this' parameter isn't declared in method scope if (symbol is ParameterSymbol param && param.IsThis) { return; } if (_localToScope.TryGetValue(symbol, out var declScope)) { declScope.DeclaredVariables.Add(symbol); } else { // Parameters and locals from expression tree lambdas // don't get recorded Debug.Assert(_inExpressionTree); } } }
public void Empty() { var dict = new SmallDictionary<int, string>(); Assert.AreEqual(0, dict.Count); string output; Assert.IsFalse(dict.TryGetValue(2, out output)); Assert.IsNull(output); Assert.IsFalse(dict.ContainsKey(3)); }
private LocalFuncUsages GetOrCreateLocalFuncUsages(LocalFunctionSymbol localFunc) { LocalFuncUsages usages; if (!_localFuncVarUsages.TryGetValue(localFunc, out usages)) { usages = _localFuncVarUsages[localFunc] = new LocalFuncUsages(UnreachableState()); } return(usages); }
private LocalFuncUsages GetOrCreateLocalFuncUsages(LocalFunctionSymbol localFunc) { LocalFuncUsages usages; if (!_localFuncVarUsages.TryGetValue(localFunc, out usages)) { usages = new LocalFuncUsages(); _localFuncVarUsages[localFunc] = usages; } return(usages); }
protected TLocalFunctionState GetOrCreateLocalFuncUsages(LocalFunctionSymbol localFunc) { _localFuncVarUsages ??= new SmallDictionary <LocalFunctionSymbol, TLocalFunctionState>(); if (!_localFuncVarUsages.TryGetValue(localFunc, out TLocalFunctionState usages)) { usages = CreateLocalFunctionState(); _localFuncVarUsages[localFunc] = usages; } return(usages); }
protected sealed override TypeSymbol SubstituteTypeParameter(TypeParameterSymbol typeParameter) { // It might need to be substituted directly. TypeSymbol result; if (Mapping.TryGetValue(typeParameter, out result)) { return(result); } return(typeParameter); }
protected sealed override TypeWithAnnotations SubstituteTypeParameter(TypeParameterSymbol typeParameter) { // It might need to be substituted directly. TypeWithAnnotations result; if (Mapping.TryGetValue(typeParameter, out result)) { return(result); } return(TypeWithAnnotations.Create(typeParameter)); }
protected sealed override TypeWithModifiers SubstituteTypeParameter(TypeParameterSymbol typeParameter) { // It might need to be substituted directly. TypeWithModifiers result; if (Mapping.TryGetValue(typeParameter, out result)) { if (typeParameter.NullabilityPreservation == CodeAnalysis.Symbols.NullabilityPreservationKind.None && result.Type.Kind == SymbolKind.NonNullableReference) { return(new TypeWithModifiers(((NonNullableReferenceTypeSymbol)result.Type).UnderlyingType)); } return(result); } return(new TypeWithModifiers(typeParameter)); }
/// <summary> /// Report an error if adding the edge (method1, method2) to the ctor-initializer /// graph would add a new cycle to that graph. /// </summary> /// <param name="method1">a calling ctor</param> /// <param name="method2">the chained-to ctor</param> /// <param name="syntax">where to report a cyclic error if needed</param> /// <param name="diagnostics">a diagnostic bag for receiving the diagnostic</param> internal void ReportCtorInitializerCycles(MethodSymbol method1, MethodSymbol method2, CSharpSyntaxNode syntax, DiagnosticBag diagnostics) { // precondition and postcondition: the graph _constructorInitializers is acyclic. // If adding the edge (method1, method2) would induce a cycle, we report an error // and do not add it to the set of edges. If it would not induce a cycle we add // it to the set of edges and return. if (method1 == method2) { // direct recursion is diagnosed elsewhere throw ExceptionUtilities.Unreachable; } if (_constructorInitializers == null) { _constructorInitializers = new SmallDictionary <MethodSymbol, MethodSymbol>(); _constructorInitializers.Add(method1, method2); return; } MethodSymbol next = method2; while (true) { if (_constructorInitializers.TryGetValue(next, out next)) { Debug.Assert((object)next != null); if (method1 == next) { // We found a (new) cycle containing the edge (method1, method2). Report an // error and do not add the edge. diagnostics.Add(ErrorCode.ERR_IndirectRecursiveConstructorCall, syntax.Location, method1); return; } } else { // we've reached the end of the path without finding a cycle. Add the new edge. _constructorInitializers.Add(method1, method2); return; } } }
/// <summary> /// Given a meaning, ensure that it is the only meaning within this scope (or report a diagnostic that it isn't). /// Returns true if a diagnostic was reported. Sets done=true if there is no need to check further enclosing /// scopes (for example, when this meaning is the same as a previous meaning, or it can be determined that a /// diagnostic had previously been reported). /// </summary> private bool EnsureSingleDefinition(SingleMeaning newMeaning, DiagnosticBag diagnostics, ref bool done) { if (singleMeaningTable == null) { Interlocked.CompareExchange(ref singleMeaningTable, new SmallDictionary <string, SingleMeaning>(), null); } lock (singleMeaningTable) { SingleMeaning oldMeaning; if (singleMeaningTable.TryGetValue(newMeaning.Name, out oldMeaning)) { if (oldMeaning.Direct) { return(ResolveConflict(oldMeaning, newMeaning, diagnostics, ref done)); } else { if (newMeaning.Direct) { singleMeaningTable[newMeaning.Name] = newMeaning; return(ResolveConflict(oldMeaning, newMeaning, diagnostics, ref done)); } else { // both indirect if ((object)oldMeaning.Symbol != null && newMeaning.Symbol == oldMeaning.Symbol && !newMeaning.IsDefinition) { done = true; // optimization } return(false); } } } else { singleMeaningTable.Add(newMeaning.Name, newMeaning); return(false); } } }
private static void DecodeGlobalSuppressMessageAttributes(Compilation compilation, ISymbol symbol, GlobalSuppressions globalSuppressions, IEnumerable <AttributeData> attributes) { foreach (var instance in attributes) { SuppressMessageInfo info; if (!TryDecodeSuppressMessageAttributeData(instance, out info)) { continue; } string scopeString = info.Scope != null?info.Scope.ToLowerInvariant() : null; TargetScope scope; if (s_suppressMessageScopeTypes.TryGetValue(scopeString, out scope)) { if ((scope == TargetScope.Module || scope == TargetScope.None) && info.Target == null) { // This suppression is applies to the entire compilation globalSuppressions.AddCompilationWideSuppression(info); continue; } } else { // Invalid value for scope continue; } // Decode Target if (info.Target == null) { continue; } foreach (var target in ResolveTargetSymbols(compilation, info.Target, scope)) { globalSuppressions.AddGlobalSymbolSuppression(target, info); } } }
private static bool TryGetTargetScope(SuppressMessageInfo info, out TargetScope scope) => s_suppressMessageScopeTypes.TryGetValue(info.Scope ?? string.Empty, out scope);
public ITsString get_String(int ws) { ITsString tss; return(m_strings.TryGetValue(ws, out tss) ? tss : TsStringUtils.EmptyString(ws)); }
public void Remove() { var dict = new SmallDictionary<int, string>(); Assert.IsFalse(dict.Remove(2), "Remove a missing item from an empty dictionary"); dict.Add(2, "abc"); Assert.IsFalse(dict.Remove(3), "Remove a missing item from a dictionary with one item"); Assert.IsTrue(dict.Remove(2), "Remove the only item from a dictionary"); Assert.AreEqual(0, dict.Count, "Nothing remains after removing the only item"); dict.Add(2, "abc"); dict.Add(5, "def"); dict.Add(11, "third"); Assert.IsFalse(dict.Remove(7), "Remove a missing item from a dictionary with three items"); Assert.IsTrue(dict.Remove(2), "Remove the first item from a dictionary with three items"); Assert.AreEqual(2, dict.Count, "Two items remain after removing the first of three"); string output; Assert.IsFalse(dict.TryGetValue(2, out output), "Removed item (first) should be gone from original three"); Assert.AreEqual("def", dict[5]); Assert.AreEqual("third", dict[11]); dict.Add(2, "abc"); Assert.IsTrue(dict.Remove(5), "Remove first of two items in others"); Assert.AreEqual(2, dict.Count); Assert.IsFalse(dict.TryGetValue(5, out output)); Assert.AreEqual("abc", dict[2]); Assert.AreEqual("third", dict[11]); Assert.IsTrue(dict.Remove(2), "Remove only item in others"); Assert.AreEqual(1, dict.Count); Assert.IsFalse(dict.TryGetValue(2, out output)); Assert.AreEqual("third", dict[11]); Assert.IsTrue(dict.Remove(11), "Remove only item in dictionary which previously had three"); Assert.AreEqual(0, dict.Count); Assert.IsFalse(dict.TryGetValue(11, out output)); dict.Add(2, "abc"); dict.Add(5, "def"); dict.Add(11, "third"); dict.Add(13, "fourth"); Assert.IsTrue(dict.Remove(11), "Remove middle of three items in others"); Assert.AreEqual(3, dict.Count); Assert.IsFalse(dict.TryGetValue(11, out output)); Assert.AreEqual("abc", dict[2]); Assert.AreEqual("def", dict[5]); Assert.AreEqual("fourth", dict[13]); Assert.IsTrue(dict.Remove(13), "Remove last of two items in others"); Assert.AreEqual(2, dict.Count); Assert.IsFalse(dict.TryGetValue(13, out output)); Assert.AreEqual("abc", dict[2]); Assert.AreEqual("def", dict[5]); Assert.IsTrue(dict.Remove(2), "Remove first item when others contains exactly one"); Assert.AreEqual(1, dict.Count); Assert.IsFalse(dict.TryGetValue(2, out output)); Assert.AreEqual("def", dict[5]); }