예제 #1
0
        public void Generate(CodeGenerator generator)
        {
            generator.EnterElement(this);

            if (ArrayElementType != null)
            {
                ArrayElementType.Generate(generator);
                generator.Write(TokenType.Punctuation, ArraySuffix);
                generator.ExitElement();
                return;
            }

            var name = RawName;

            if (SimplifiedBuiltinTypeNames.TryGetValue(name, out var simplifiedBuiltinTypeName))
            {
                generator.Write(TokenType.Keyword, simplifiedBuiltinTypeName);
                generator.ExitElement();
                return;
            }

            if (name == "var")
            {
                generator.Write(TokenType.Keyword, name);
                generator.ExitElement();
                return;
            }

            if (Global)
            {
                generator.Write(TokenType.Keyword, "global");
                generator.Write(TokenType.Punctuation, "::");
            }

            var nameBuilder         = new StringBuilder();
            var namespaceNameLength = 0;

            {
                var previousIndex = 0;

                for (var i = 0; i < name.Length; i++)
                {
                    var c = name[i];
                    if (c == '.')
                    {
                        nameBuilder.Append(name.Substring(previousIndex, i - previousIndex).EscapeIdentifier());
                        namespaceNameLength = nameBuilder.Length;
                        nameBuilder.Append('.');
                        previousIndex = i + 1;
                    }
                    else if (c == '+')
                    {
                        nameBuilder.Append(name.Substring(previousIndex, i - previousIndex).EscapeIdentifier()).Append('.');
                        previousIndex = i + 1;
                    }
                }

                nameBuilder.Append(previousIndex > 0 ? name.Substring(previousIndex).EscapeIdentifier() : name.EscapeUnqualifiedTypeIdentifier());
            }

            if (namespaceNameLength > 0)
            {
                var namespaceRef = new CodeUsingImport(nameBuilder.ToString(0, namespaceNameLength));

                var usingSets = generator.UsingSets;

                foreach (var usingSet in usingSets)
                {
                    if (usingSet.Contains(namespaceRef))
                    {
                        var ambiguityDetected            = false;
                        var unqualifiedTypeName          = nameBuilder.ToString(namespaceNameLength + 1, nameBuilder.Length - namespaceNameLength - 1);
                        var unqualifiedTypeNameWithArity = unqualifiedTypeName + (TypeArguments != null && TypeArguments.Count != 0 ? "`" + TypeArguments.Count : "");

                        if (TypesByNames.TryGetValue(unqualifiedTypeNameWithArity, out var types))
                        {
                            foreach (var type in types)
                            {
                                var otherNamespaceRef = new CodeUsingImport(type.NamespaceName);

                                if (namespaceRef != otherNamespaceRef)
                                {
                                    foreach (var otherUsingSet in usingSets)
                                    {
                                        if (otherUsingSet.Contains(otherNamespaceRef))
                                        {
                                            ambiguityDetected = true;
                                            break;
                                        }
                                    }
                                }

                                if (ambiguityDetected)
                                {
                                    break;
                                }
                            }
                        }

                        ambiguityDetected = ambiguityDetected || generator.Options.PredeclaredTypes.Where(type => type.NamespaceName != namespaceRef.Name && type.TypeName == unqualifiedTypeNameWithArity).Any();

                        if (!ambiguityDetected)
                        {
                            nameBuilder.Length = 0;
                            nameBuilder.Append(unqualifiedTypeName);
                        }

                        break;
                    }
                }
            }

            {
                var previousIndex = 0;

                var typeArgumentStart = 0;

                for (var characterIndex = 0; characterIndex < nameBuilder.Length;)
                {
                    if (nameBuilder[characterIndex] == '`')
                    {
                        generator.OutputQualifiedName(TokenType.TypeIdentifier, nameBuilder, previousIndex, characterIndex);

                        characterIndex++;

                        var arity = 0;

                        while (characterIndex < nameBuilder.Length && '0' <= nameBuilder[characterIndex] && nameBuilder[characterIndex] <= '9')
                        {
                            arity = arity * 10 + (nameBuilder[characterIndex] - '0');
                            characterIndex++;
                        }

                        previousIndex = characterIndex;

                        generator.Write(TokenType.Punctuation, '<');

                        var first = true;

                        for (var typeArgumentIndex = typeArgumentStart; typeArgumentIndex < typeArgumentStart + arity; typeArgumentIndex++)
                        {
                            var typeArgument = TypeArguments[typeArgumentIndex];

                            if (first)
                            {
                                first = false;
                            }
                            else
                            {
                                generator.Write(TokenType.Punctuation, ',');
                                if (typeArgument != null)
                                {
                                    generator.Write(TokenType.Space, ' ');
                                }
                            }

                            if (typeArgument != null)
                            {
                                typeArgument.Generate(generator);
                            }
                        }

                        typeArgumentStart += arity;

                        generator.Write(TokenType.Punctuation, '>');
                    }
                    else
                    {
                        characterIndex++;
                    }
                }

                if (previousIndex < nameBuilder.Length)
                {
                    generator.OutputQualifiedName(TokenType.TypeIdentifier, nameBuilder, previousIndex);
                }
            }

            generator.ExitElement();
        }