예제 #1
0
        public static void BuildNamedTypeDisplayName(this INamedTypeSymbol namedType, Context cx, ITrapBuilder tb)
        {
            if (namedType.IsTupleType)
            {
                tb.Append("(");
                tb.BuildList(",", namedType.TupleElements.Select(f => f.Type),
                             (t, tb0) => t.BuildDisplayName(cx, tb0)
                             );

                tb.Append(")");
                return;
            }

            if (namedType.IsAnonymousType)
            {
                namedType.BuildAnonymousName(cx, tb, (cx0, tb0, sub) => sub.BuildDisplayName(cx0, tb0), false);
            }

            tb.Append(namedType.Name);
            if (namedType.IsGenericType && namedType.TypeKind != TypeKind.Error && namedType.TypeArguments.Any())
            {
                tb.Append("<");
                tb.BuildList(",", namedType.TypeArguments, (p, tb0) =>
                {
                    if (IsReallyBound(namedType))
                    {
                        p.BuildDisplayName(cx, tb0);
                    }
                });
                tb.Append(">");
            }
        }
예제 #2
0
 public void AppendTo(ITrapBuilder tb)
 {
     tb.Append("@\"");
     foreach (var fragment in TrapBuilder.Fragments)
     {
         tb.Append(fragment);
     }
     tb.Append("\"");
 }
예제 #3
0
 /// <summary>
 /// Constructs an array suffix string for this array type symbol.
 /// </summary>
 /// <param name="tb">The trap builder used to store the result.</param>
 public static void BuildArraySuffix(this IArrayTypeSymbol array, ITrapBuilder tb)
 {
     tb.Append("[");
     for (int i = 0; i < array.Rank - 1; i++)
     {
         tb.Append(",");
     }
     tb.Append("]");
 }
예제 #4
0
        /// <summary>
        /// Constructs a unique string for this type symbol.
        ///
        /// The supplied action <paramref name="subTermAction"/> is applied to the
        /// syntactic sub terms of this type (if any).
        /// </summary>
        /// <param name="cx">The extraction context.</param>
        /// <param name="tb">The trap builder used to store the result.</param>
        /// <param name="subTermAction">The action to apply to syntactic sub terms of this type.</param>
        public static void BuildTypeId(this ITypeSymbol type, Context cx, ITrapBuilder tb, Action <Context, ITrapBuilder, ITypeSymbol> subTermAction)
        {
            if (type.SpecialType != SpecialType.None)
            {
                /*
                 * Use the keyword ("int" etc) for the built-in types.
                 * This makes the IDs shorter and means that all built-in types map to
                 * the same entities (even when using multiple versions of mscorlib).
                 */
                tb.Append(type.ToDisplayString());
                return;
            }

            using (cx.StackGuard)
            {
                switch (type.TypeKind)
                {
                case TypeKind.Array:
                    var array = (IArrayTypeSymbol)type;
                    subTermAction(cx, tb, array.ElementType);
                    array.BuildArraySuffix(tb);
                    return;

                case TypeKind.Class:
                case TypeKind.Interface:
                case TypeKind.Struct:
                case TypeKind.Enum:
                case TypeKind.Delegate:
                case TypeKind.Error:
                    var named = (INamedTypeSymbol)type;
                    named.BuildNamedTypeId(cx, tb, subTermAction);
                    return;

                case TypeKind.Pointer:
                    var ptr = (IPointerTypeSymbol)type;
                    subTermAction(cx, tb, ptr.PointedAtType);
                    tb.Append("*");
                    return;

                case TypeKind.TypeParameter:
                    var tp = (ITypeParameterSymbol)type;
                    tb.Append(tp.Name);
                    return;

                case TypeKind.Dynamic:
                    tb.Append("dynamic");
                    return;

                default:
                    throw new InternalError(type, $"Unhandled type kind '{type.TypeKind}'");
                }
            }
        }
예제 #5
0
 public void EmitToTrapBuilder(ITrapBuilder tb)
 {
     label.AppendTo(tb);
     tb.Append("=");
     id.AppendTo(tb);
     tb.AppendLine();
 }
예제 #6
0
        /// <summary>
        /// Constructs a display name string for this type symbol.
        /// </summary>
        /// <param name="tb">The trap builder used to store the result.</param>
        public static void BuildDisplayName(this ITypeSymbol type, Context cx, ITrapBuilder tb)
        {
            using (cx.StackGuard)
            {
                switch (type.TypeKind)
                {
                case TypeKind.Array:
                    var array       = (IArrayTypeSymbol)type;
                    var elementType = array.ElementType;
                    if (elementType.MetadataName.IndexOf("`") >= 0)
                    {
                        tb.Append(elementType.Name);
                        return;
                    }
                    elementType.BuildDisplayName(cx, tb);
                    array.BuildArraySuffix(tb);
                    return;

                case TypeKind.Class:
                case TypeKind.Interface:
                case TypeKind.Struct:
                case TypeKind.Enum:
                case TypeKind.Delegate:
                case TypeKind.Error:
                    var named = (INamedTypeSymbol)type;
                    named.BuildNamedTypeDisplayName(cx, tb);
                    return;

                case TypeKind.Pointer:
                    var ptr = (IPointerTypeSymbol)type;
                    ptr.PointedAtType.BuildDisplayName(cx, tb);
                    tb.Append("*");
                    return;

                case TypeKind.TypeParameter:
                    tb.Append(type.Name);
                    return;

                case TypeKind.Dynamic:
                    tb.Append("dynamic");
                    return;

                default:
                    throw new InternalError(type, $"Unhandled type kind '{type.TypeKind}'");
                }
            }
        }
예제 #7
0
        /// <summary>
        /// Constructs a unique string for this label.
        /// </summary>
        /// <param name="tb">The trap builder used to store the result.</param>
        public void AppendTo(ITrapBuilder tb)
        {
            if (!Valid)
            {
                throw new NullReferenceException("Attempt to use an invalid label");
            }

            tb.Append("#").Append(Value);
        }
예제 #8
0
        static void BuildAnonymousName(this ITypeSymbol type, Context cx, ITrapBuilder tb, Action <Context, ITrapBuilder, ITypeSymbol> subTermAction, bool includeParamName)
        {
            var buildParam = includeParamName
                ? (prop, tb0) =>
            {
                tb0.Append(prop.Name).Append(" ");
                subTermAction(cx, tb0, prop.Type);
            }
            : (Action <IPropertySymbol, ITrapBuilder>)((prop, tb0) => subTermAction(cx, tb0, prop.Type));
            int memberCount    = type.GetMembers().OfType <IPropertySymbol>().Count();
            int hackTypeNumber = memberCount == 1 ? 1 : 0;

            tb.Append("<>__AnonType");
            tb.Append(hackTypeNumber);
            tb.Append("<");
            tb.BuildList(",", type.GetMembers().OfType <IPropertySymbol>(), buildParam);
            tb.Append(">");
        }
예제 #9
0
파일: Method.cs 프로젝트: xcorail/ql
 /// <summary>
 /// Adds an appropriate label ID to the trap builder <paramref name="tb"/>
 /// for the type <paramref name="type"/> belonging to the signature of method
 /// <paramref name="method"/>.
 ///
 /// For methods without type parameters this will always add the key of the
 /// corresponding type.
 ///
 /// For methods with type parameters, this will add the key of the
 /// corresponding type if the type does *not* contain one of the method
 /// type parameters, otherwise it will add a textual representation of
 /// the type. This distinction is required because type parameter IDs
 /// refer to their declaring methods.
 ///
 /// Example:
 ///
 /// <code>
 /// int Count&lt;T&gt;(IEnumerable<T> items)
 /// </code>
 ///
 /// The label definitions for <code>Count</code> (<code>#4</code>) and <code>T</code>
 /// (<code>#5</code>) will look like:
 ///
 /// <code>
 /// #1=&lt;label for System.Int32&gt;
 /// #2=&lt;label for type containing Count&gt;
 /// #3=&lt;label for IEnumerable`1&gt;
 /// #4=@"{#1} {#2}.Count`2(#3<T>);method"
 /// #5=@"{#4}T;typeparameter"
 /// </code>
 ///
 /// Note how <code>int</code> is referenced in the label definition <code>#3</code> for
 /// <code>Count</code>, while <code>T[]</code> is represented textually in order
 /// to make the reference to <code>#3</code> in the label definition <code>#4</code> for
 /// <code>T</code> valid.
 /// </summary>
 protected static void AddSignatureTypeToId(Context cx, ITrapBuilder tb, IMethodSymbol method, ITypeSymbol type)
 {
     if (type.ContainsTypeParameters(cx, method))
     {
         type.BuildTypeId(cx, tb, (cx0, tb0, type0) => AddSignatureTypeToId(cx, tb0, method, type0));
     }
     else
     {
         tb.Append(Type.Create(cx, type));
     }
 }
예제 #10
0
        static void BuildNamespace(this INamespaceSymbol ns, Context cx, ITrapBuilder tb)
        {
            // Only include the assembly information in each type ID
            // for normal extractions. This is because standalone extractions
            // lack assembly information or may be ambiguous.
            bool prependAssemblyToTypeId = !cx.Extractor.Standalone && ns.ContainingAssembly != null;

            if (prependAssemblyToTypeId)
            {
                // Note that we exclude the revision number as this has
                // been observed to be unstable.
                var assembly = ns.ContainingAssembly.Identity;
                tb.Append(assembly.Name).Append("_").
                Append(assembly.Version.Major).Append(".").
                Append(assembly.Version.Minor).Append(".").
                Append(assembly.Version.Build).Append("::");
            }

            tb.Append(Namespace.Create(cx, ns)).Append(".");
        }
예제 #11
0
        static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, ITrapBuilder tb, Action <Context, ITrapBuilder, ITypeSymbol> subTermAction)
        {
            if (named.IsTupleType)
            {
                tb.Append("(");
                tb.BuildList(",", named.TupleElements,
                             (f, tb0) =>
                {
                    tb.Append(f.Name).Append(":");
                    subTermAction(cx, tb0, f.Type);
                }
                             );
                tb.Append(")");
                return;
            }

            if (named.ContainingType != null)
            {
                subTermAction(cx, tb, named.ContainingType);
                tb.Append(".");
            }
            else if (named.ContainingNamespace != null)
            {
                named.ContainingNamespace.BuildNamespace(cx, tb);
            }

            if (named.IsAnonymousType)
            {
                named.BuildAnonymousName(cx, tb, subTermAction, true);
            }
            else if (named.TypeParameters.IsEmpty)
            {
                tb.Append(named.Name);
            }
            else if (IsReallyUnbound(named))
            {
                tb.Append(named.Name).Append("`").Append(named.TypeParameters.Length);
            }
            else
            {
                subTermAction(cx, tb, named.ConstructedFrom);
                tb.Append("<");
                // Encode the nullability of the type arguments in the label.
                // Type arguments with different nullability can result in
                // a constructed type with different nullability of its members and methods,
                // so we need to create a distinct database entity for it.
                tb.BuildList(",", named.GetAnnotatedTypeArguments(), (ta, tb0) => { subTermAction(cx, tb0, ta.Symbol); tb.Append((int)ta.Nullability); });
                tb.Append(">");
            }
        }
예제 #12
0
        static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, ITrapBuilder tb, Action <Context, ITrapBuilder, ITypeSymbol> subTermAction)
        {
            if (named.IsTupleType)
            {
                tb.Append("(");
                tb.BuildList(",", named.TupleElements,
                             (f, tb0) =>
                {
                    tb.Append(f.Name).Append(":");
                    subTermAction(cx, tb0, f.Type);
                }
                             );
                tb.Append(")");
                return;
            }

            if (named.ContainingType != null)
            {
                subTermAction(cx, tb, named.ContainingType);
                tb.Append(".");
            }
            else if (named.ContainingNamespace != null)
            {
                named.ContainingNamespace.BuildNamespace(cx, tb);
            }

            if (named.IsAnonymousType)
            {
                named.BuildAnonymousName(cx, tb, subTermAction, true);
            }
            else if (named.TypeParameters.IsEmpty)
            {
                tb.Append(named.Name);
            }
            else if (IsReallyUnbound(named))
            {
                tb.Append(named.Name).Append("`").Append(named.TypeParameters.Length);
            }
            else
            {
                subTermAction(cx, tb, named.ConstructedFrom);
                tb.Append("<");
                tb.BuildList(",", named.TypeArguments, (ta, tb0) => subTermAction(cx, tb0, ta));
                tb.Append(">");
            }
        }
예제 #13
0
        /// <summary>
        /// Builds a trap builder using a separator and an action for each item in the list.
        /// </summary>
        /// <typeparam name="T">The type of the items.</typeparam>
        /// <param name="tb">The trap builder to append to.</param>
        /// <param name="separator">The separator string (e.g. ",")</param>
        /// <param name="items">The list of items.</param>
        /// <param name="action">The action on each item.</param>
        /// <returns>The original trap builder (fluent interface).</returns>
        public static ITrapBuilder BuildList <T>(this ITrapBuilder tb, string separator, IEnumerable <T> items, Action <T, ITrapBuilder> action)
        {
            bool first = true;

            foreach (var item in items)
            {
                if (first)
                {
                    first = false;
                }
                else
                {
                    tb.Append(separator);
                }
                action(item, tb);
            }
            return(tb);
        }
예제 #14
0
파일: Method.cs 프로젝트: xcorail/ql
        /// <summary>
        ///  Factored out to share logic between `Method` and `UserOperator`.
        /// </summary>
        protected static void BuildMethodId(Method m, ITrapBuilder tb)
        {
            tb.Append(m.ContainingType);

            AddExplicitInterfaceQualifierToId(m.Context, tb, m.symbol.ExplicitInterfaceImplementations);

            tb.Append(".").Append(m.symbol.Name);

            if (m.symbol.IsGenericMethod)
            {
                if (Equals(m.symbol, m.symbol.OriginalDefinition))
                {
                    tb.Append("`").Append(m.symbol.TypeParameters.Length);
                }
                else
                {
                    tb.Append("<");
                    // Encode the nullability of the type arguments in the label.
                    // Type arguments with different nullability can result in
                    // a constructed method with different nullability of its parameters and return type,
                    // so we need to create a distinct database entity for it.
                    tb.BuildList(",", m.symbol.GetAnnotatedTypeArguments(), (ta, tb0) => { AddSignatureTypeToId(m.Context, tb0, m.symbol, ta.Symbol); tb.Append((int)ta.Nullability); });
                    tb.Append(">");
                }
            }

            AddParametersToId(m.Context, tb, m.symbol);
            switch (m.symbol.MethodKind)
            {
            case MethodKind.PropertyGet:
                tb.Append(";getter");
                break;

            case MethodKind.PropertySet:
                tb.Append(";setter");
                break;

            case MethodKind.EventAdd:
                tb.Append(";adder");
                break;

            case MethodKind.EventRaise:
                tb.Append(";raiser");
                break;

            case MethodKind.EventRemove:
                tb.Append(";remover");
                break;

            default:
                tb.Append(";method");
                break;
            }
        }
예제 #15
0
 public void AppendTo(ITrapBuilder tb)
 {
     tb.Append("*");
 }
예제 #16
0
파일: Tuple.cs 프로젝트: lcartey/codeql
 private static void WriteString(ITrapBuilder tb, string s) => tb.Append(EncodeString(s));
예제 #17
0
 public void EmitToTrapBuilder(ITrapBuilder tb)
 {
     tb.Append(".push ");
     Key.AppendTo(tb);
     tb.AppendLine();
 }
예제 #18
0
파일: Id.cs 프로젝트: zarulshahrin/ql
 public void AppendTo(ITrapBuilder tb)
 {
     tb.Append("@\"");
     BuildParts(tb);
     tb.Append("\"");
 }
예제 #19
0
        /// <summary>
        ///  Factored out to share logic between `Method` and `UserOperator`.
        /// </summary>
        protected static void BuildMethodId(Method m, ITrapBuilder tb)
        {
            tb.Append(m.ContainingType);

            AddExplicitInterfaceQualifierToId(m.Context, tb, m.symbol.ExplicitInterfaceImplementations);

            tb.Append(".").Append(m.symbol.Name);

            if (m.symbol.IsGenericMethod)
            {
                if (Equals(m.symbol, m.symbol.OriginalDefinition))
                {
                    tb.Append("`").Append(m.symbol.TypeParameters.Length);
                }
                else
                {
                    tb.Append("<");
                    tb.BuildList(",", m.symbol.TypeArguments, (ta, tb0) => AddSignatureTypeToId(m.Context, tb0, m.symbol, ta));
                    tb.Append(">");
                }
            }

            AddParametersToId(m.Context, tb, m.symbol);
            switch (m.symbol.MethodKind)
            {
            case MethodKind.PropertyGet:
                tb.Append(";getter");
                break;

            case MethodKind.PropertySet:
                tb.Append(";setter");
                break;

            case MethodKind.EventAdd:
                tb.Append(";adder");
                break;

            case MethodKind.EventRaise:
                tb.Append(";raiser");
                break;

            case MethodKind.EventRemove:
                tb.Append(";remover");
                break;

            default:
                tb.Append(";method");
                break;
            }
        }
예제 #20
0
 public void EmitToTrapBuilder(ITrapBuilder tb)
 {
     tb.Append(Content);
 }
예제 #21
0
파일: Method.cs 프로젝트: xcorail/ql
 protected static void AddParametersToId(Context cx, ITrapBuilder tb, IMethodSymbol method)
 {
     tb.Append("(");
     tb.AppendList(",", AddParameterPartsToId(cx, tb, method));
     tb.Append(")");
 }
예제 #22
0
파일: Id.cs 프로젝트: zarulshahrin/ql
 public override void BuildParts(ITrapBuilder tb)
 {
     tb.Append(value);
 }
예제 #23
0
파일: Tuple.cs 프로젝트: lcartey/codeql
        /// <summary>
        /// Constructs a unique string for this tuple.
        /// </summary>
        /// <param name="tb">The trap builder used to store the result.</param>
        public void EmitToTrapBuilder(ITrapBuilder tb)
        {
            tb.Append(Name).Append("(");

            int column = 0;

            foreach (var a in Args)
            {
                if (column > 0)
                {
                    tb.Append(", ");
                }
                switch (a)
                {
                case Label l:
                    l.AppendTo(tb);
                    break;

                case IEntity e:
                    e.Label.AppendTo(tb);
                    break;

                case string s:
                    tb.Append("\"");
                    if (NeedsTruncation(s))
                    {
                        // Slow path
                        int remaining = maxStringBytes;
                        WriteTruncatedString(tb, s, ref remaining);
                    }
                    else
                    {
                        // Fast path
                        WriteString(tb, s);
                    }
                    tb.Append("\"");
                    break;

                case System.Enum _:
                    tb.Append((int)a);
                    break;

                case int i:
                    tb.Append(i);
                    break;

                case float f:
                    tb.Append(f.ToString("0.#####e0"));      // Trap importer won't accept ints
                    break;

                case string[] array:
                    tb.Append("\"");
                    if (NeedsTruncation(array))
                    {
                        // Slow path
                        int remaining = maxStringBytes;
                        foreach (var element in array)
                        {
                            WriteTruncatedString(tb, element, ref remaining);
                        }
                    }
                    else
                    {
                        // Fast path
                        foreach (var element in array)
                        {
                            WriteString(tb, element);
                        }
                    }
                    tb.Append("\"");
                    break;

                case null:
                    throw new InternalError($"Attempt to write a null argument tuple {Name} at column {column}");

                default:
                    throw new InternalError($"Attempt to write an invalid argument type {a.GetType()} in tuple {Name} at column {column}");
                }

                ++column;
            }
            tb.Append(")");
            tb.AppendLine();
        }
예제 #24
0
 public void EmitToTrapBuilder(ITrapBuilder tb)
 {
     tb.Append(".pop");
     tb.AppendLine();
 }
예제 #25
0
파일: Tuple.cs 프로젝트: safl/ql
        /// <summary>
        /// Constructs a unique string for this tuple.
        /// </summary>
        /// <param name="tb">The trap builder used to store the result.</param>
        public void EmitToTrapBuilder(ITrapBuilder tb)
        {
            tb.Append(Name).Append("(");

            int column = 0;

            foreach (var a in Args)
            {
                if (column > 0)
                {
                    tb.Append(", ");
                }
                if (a is Label)
                {
                    ((Label)a).AppendTo(tb);
                }
                else if (a is IEntity)
                {
                    ((IEntity)a).Label.AppendTo(tb);
                }
                else if (a is string)
                {
                    tb.Append("\"");
                    tb.Append(((string)a).Replace("\"", "\"\""));
                    tb.Append("\"");
                }
                else if (a is System.Enum)
                {
                    tb.Append((int)a);
                }
                else if (a is int)
                {
                    tb.Append((int)a);
                }
                else if (a == null)
                {
                    throw new InternalError("Attempt to write a null argument tuple {0} at column {1}",
                                            Name, column);
                }
                else
                {
                    var array = a as string[];
                    if (array != null)
                    {
                        tb.Append("\"");
                        foreach (var element in array)
                        {
                            tb.Append(element.Replace("\"", "\"\""));
                        }
                        tb.Append("\"");
                    }
                    else
                    {
                        throw new InternalError("Attempt to write an invalid argument type {0} in tuple {1} at column {2}",
                                                a.GetType(), Name, column);
                    }
                }
                ++column;
            }
            tb.Append(")");
            tb.AppendLine();
        }