private NativeImportRecord(
     ImportTargetKind targetKind,
     string externAlias,
     string alias,
     string targetString)
 {
     _targetKind = targetKind;
     _externAlias = externAlias;
     _alias = alias;
     _targetString = targetString;
 }
Exemple #2
0
 public ImportRecord(
     ImportTargetKind targetKind,
     string alias = null,
     ITypeSymbol targetType = null,
     string targetString = null,
     IAssemblySymbol targetAssembly = null,
     string targetAssemblyAlias = null)
 {
     TargetKind = targetKind;
     Alias = alias;
     TargetType = targetType;
     TargetString = targetString;
     TargetAssembly = targetAssembly;
     TargetAssemblyAlias = targetAssemblyAlias;
 }
        /// <summary>
        /// Parse a string representing a VB import statement.
        /// </summary>
        /// <exception cref="ArgumentNullException"><paramref name="import"/> is null.</exception>
        /// <exception cref="ArgumentException">Format of <paramref name="import"/> is not valid.</exception>
        public static void ParseVisualBasicImportString(string import, out string alias, out string target, out ImportTargetKind kind, out ImportScope scope)
        {
            if (import == null)
            {
                throw new ArgumentNullException("import");
            }

            if (import.Length == 0) // VB current namespace
            {
                alias = null;
                target = import;
                kind = ImportTargetKind.CurrentNamespace;
                scope = ImportScope.Unspecified;
                return;
            }

            int pos = 0;
            switch (import[pos])
            {
                case '*': // VB default namespace
                    // see PEBuilder.cpp in vb\language\CodeGen
                    pos++;
                    alias = null;
                    target = import.Substring(pos);
                    kind = ImportTargetKind.DefaultNamespace;
                    scope = ImportScope.Unspecified;
                    return;
                case '@': // VB cases other than default and current namespace
                    // see PEBuilder.cpp in vb\language\CodeGen
                    pos++;
                    if (pos >= import.Length)
                    {
                        throw new ArgumentException(import, "import");
                    }

                    scope = ImportScope.Unspecified;
                    switch (import[pos])
                    {
                        case 'F':
                            scope = ImportScope.File;
                            pos++;
                            break;
                        case 'P':
                            scope = ImportScope.Project;
                            pos++;
                            break;
                    }

                    if (pos >= import.Length)
                    {
                        throw new ArgumentException(import, "import");
                    }

                    switch (import[pos])
                    {
                        case 'A':
                            pos++;
                            if (import[pos] != ':')
                            {
                                throw new ArgumentException(import, "import");
                            }
                            pos++;

                            if (!TrySplit(import, pos, '=', out alias, out target))
                            {
                                throw new ArgumentException(import, "import");
                            }

                            kind = ImportTargetKind.NamespaceOrType;
                            return;
                        case 'X':
                            pos++;
                            if (import[pos] != ':')
                            {
                                throw new ArgumentException(import, "import");
                            }
                            pos++;

                            if (!TrySplit(import, pos, '=', out alias, out target))
                            {
                                throw new ArgumentException(import, "import");
                            }

                            kind = ImportTargetKind.XmlNamespace;
                            return;
                        case 'T':
                            pos++;
                            if (import[pos] != ':')
                            {
                                throw new ArgumentException(import, "import");
                            }
                            pos++;

                            alias = null;
                            target = import.Substring(pos);
                            kind = ImportTargetKind.Type;
                            return;
                        case ':':
                            pos++;
                            alias = null;
                            target = import.Substring(pos);
                            kind = ImportTargetKind.Namespace;
                            return;
                        default:
                            alias = null;
                            target = import.Substring(pos);
                            kind = ImportTargetKind.MethodToken;
                            return;
                    }
                default: // VB current namespace
                    alias = null;
                    target = import;
                    kind = ImportTargetKind.CurrentNamespace;
                    scope = ImportScope.Unspecified;
                    return;
            }
        }
        /// <summary>
        /// Parse a string representing a C# using (or extern alias) directive.
        /// </summary>
        /// <remarks>
        /// <![CDATA[
        /// For C#:
        ///  "USystem" -> <namespace name="System" />
        ///  "AS USystem" -> <alias name="S" target="System" kind="namespace" />
        ///  "AC TSystem.Console" -> <alias name="C" target="System.Console" kind="type" />
        ///  "AS ESystem alias" -> <alias name="S" qualifier="alias" target="System" kind="type" />
        ///  "XOldLib" -> <extern alias="OldLib" />
        ///  "ZOldLib assembly" -> <externinfo name="OldLib" assembly="assembly" />
        ///  "ESystem alias" -> <namespace qualifier="alias" name="System" />
        /// ]]>
        /// </remarks>
        public static void ParseCSharpImportString(string import, out string alias, out string externAlias, out string target, out ImportTargetKind kind)
        {
            if (import == null)
            {
                throw new ArgumentNullException("import");
            }

            if (import.Length == 0)
            {
                throw new ArgumentException(import, "import");
            }

            switch (import[0])
            {
                case 'U': // C# using
                    alias = null;
                    externAlias = null;
                    target = import.Substring(1);
                    kind = ImportTargetKind.Namespace;
                    return;
                case 'E': // C# using
                    // NOTE: Dev12 has related cases "I" and "O" in EMITTER::ComputeDebugNamespace,
                    // but they were probably implementation details that do not affect roslyn.
                    if (!TrySplit(import, 1, ' ', out target, out externAlias))
                    {
                        throw new ArgumentException(import, "import");
                    }

                    alias = null;
                    kind = ImportTargetKind.Namespace;
                    return;
                case 'A': // C# type or namespace alias
                    if (!TrySplit(import, 1, ' ', out alias, out target))
                    {
                        throw new ArgumentException(import, "import");
                    }

                    switch (target[0])
                    {
                        case 'U':
                            kind = ImportTargetKind.Namespace;
                            target = target.Substring(1);
                            externAlias = null;
                            return;
                        case 'T':
                            kind = ImportTargetKind.Type;
                            target = target.Substring(1);
                            externAlias = null;
                            return;
                        case 'E':
                            kind = ImportTargetKind.Namespace; // Never happens for types.
                            if (!TrySplit(target, 1, ' ', out target, out externAlias))
                            {
                                throw new ArgumentException(import, "import");
                            }
                            return;
                        default:
                            throw new ArgumentException(import, "import");
                    }
                case 'X': // C# extern alias (in file)
                    externAlias = import.Substring(1);
                    alias = null;
                    target = null;
                    kind = ImportTargetKind.Assembly;
                    return;
                case 'Z': // C# extern alias (module-level)
                    if (!TrySplit(import, 1, ' ', out externAlias, out target))
                    {
                        throw new ArgumentException(import, "import");
                    }

                    alias = null;
                    kind = ImportTargetKind.Assembly;
                    return;
                default:
                    throw new ArgumentException(import, "import");
            }
        }
        /// <summary>
        /// Parse a string representing a VB import statement.
        /// </summary>
        /// <exception cref="ArgumentNullException"><paramref name="import"/> is null.</exception>
        /// <exception cref="ArgumentException">Format of <paramref name="import"/> is not valid.</exception>
        public static bool TryParseVisualBasicImportString(string import, out string alias, out string target, out ImportTargetKind kind, out ImportScope scope)
        {
            alias = null;
            target = null;
            kind = default(ImportTargetKind);
            scope = default(ImportScope);

            if (import == null)
            {
                return false;
            }

            // VB current namespace
            if (import.Length == 0)
            {
                alias = null;
                target = import;
                kind = ImportTargetKind.CurrentNamespace;
                scope = ImportScope.Unspecified;
                return true;
            }

            int pos = 0;
            switch (import[pos])
            {
                case '&':
                // Indicates the presence of embedded PIA types from a given assembly.  No longer required (as of Roslyn).
                case '$':
                case '#':
                    // From ProcedureContext::LoadImportsAndDefaultNamespaceNormal:
                    //   "Module Imports and extension types are no longer needed since we are not doing custom name lookup"
                    alias = null;
                    target = import;
                    kind = ImportTargetKind.Defunct;
                    scope = ImportScope.Unspecified;
                    return true;
                case '*': // VB default namespace
                    // see PEBuilder.cpp in vb\language\CodeGen
                    pos++;
                    alias = null;
                    target = import.Substring(pos);
                    kind = ImportTargetKind.DefaultNamespace;
                    scope = ImportScope.Unspecified;
                    return true;
                case '@': // VB cases other than default and current namespace
                    // see PEBuilder.cpp in vb\language\CodeGen
                    pos++;
                    if (pos >= import.Length)
                    {
                        return false;
                    }

                    scope = ImportScope.Unspecified;
                    switch (import[pos])
                    {
                        case 'F':
                            scope = ImportScope.File;
                            pos++;
                            break;
                        case 'P':
                            scope = ImportScope.Project;
                            pos++;
                            break;
                    }

                    if (pos >= import.Length)
                    {
                        return false;
                    }

                    switch (import[pos])
                    {
                        case 'A':
                            pos++;

                            if (import[pos] != ':')
                            {
                                return false;
                            }

                            pos++;

                            if (!TrySplit(import, pos, '=', out alias, out target))
                            {
                                return false;
                            }

                            kind = ImportTargetKind.NamespaceOrType;
                            return true;

                        case 'X':
                            pos++;

                            if (import[pos] != ':')
                            {
                                return false;
                            }

                            pos++;

                            if (!TrySplit(import, pos, '=', out alias, out target))
                            {
                                return false;
                            }

                            kind = ImportTargetKind.XmlNamespace;
                            return true;

                        case 'T':
                            pos++;

                            if (import[pos] != ':')
                            {
                                return false;
                            }

                            pos++;

                            alias = null;
                            target = import.Substring(pos);
                            kind = ImportTargetKind.Type;
                            return true;

                        case ':':
                            pos++;
                            alias = null;
                            target = import.Substring(pos);
                            kind = ImportTargetKind.Namespace;
                            return true;

                        default:
                            alias = null;
                            target = import.Substring(pos);
                            kind = ImportTargetKind.MethodToken;
                            return true;
                    }

                default:
                    // VB current namespace
                    alias = null;
                    target = import;
                    kind = ImportTargetKind.CurrentNamespace;
                    scope = ImportScope.Unspecified;
                    return true;
            }
        }
        /// <summary>
        /// Parse a string representing a C# using (or extern alias) directive.
        /// </summary>
        /// <remarks>
        /// <![CDATA[
        /// For C#:
        ///  "USystem" -> <namespace name="System" />
        ///  "AS USystem" -> <alias name="S" target="System" kind="namespace" />
        ///  "AC TSystem.Console" -> <alias name="C" target="System.Console" kind="type" />
        ///  "AS ESystem alias" -> <alias name="S" qualifier="alias" target="System" kind="type" />
        ///  "XOldLib" -> <extern alias="OldLib" />
        ///  "ZOldLib assembly" -> <externinfo name="OldLib" assembly="assembly" />
        ///  "ESystem alias" -> <namespace qualifier="alias" name="System" />
        ///  "TSystem.Math" -> <type name="System.Math" />
        /// ]]>
        /// </remarks>
        public static bool TryParseCSharpImportString(string import, out string alias, out string externAlias, out string target, out ImportTargetKind kind)
        {
            alias = null;
            externAlias = null;
            target = null;
            kind = default(ImportTargetKind);

            if (string.IsNullOrEmpty(import))
            {
                return false;
            }

            switch (import[0])
            {
                case 'U': // C# (namespace) using
                    alias = null;
                    externAlias = null;
                    target = import.Substring(1);
                    kind = ImportTargetKind.Namespace;
                    return true;

                case 'E': // C# (namespace) using
                    // NOTE: Dev12 has related cases "I" and "O" in EMITTER::ComputeDebugNamespace,
                    // but they were probably implementation details that do not affect Roslyn.
                    if (!TrySplit(import, 1, ' ', out target, out externAlias))
                    {
                        return false;
                    }

                    alias = null;
                    kind = ImportTargetKind.Namespace;
                    return true;

                case 'T': // C# (type) using
                    alias = null;
                    externAlias = null;
                    target = import.Substring(1);
                    kind = ImportTargetKind.Type;
                    return true;

                case 'A': // C# type or namespace alias
                    if (!TrySplit(import, 1, ' ', out alias, out target))
                    {
                        return false;
                    }

                    switch (target[0])
                    {
                        case 'U':
                            kind = ImportTargetKind.Namespace;
                            target = target.Substring(1);
                            externAlias = null;
                            return true;

                        case 'T':
                            kind = ImportTargetKind.Type;
                            target = target.Substring(1);
                            externAlias = null;
                            return true;

                        case 'E':
                            kind = ImportTargetKind.Namespace; // Never happens for types.
                            if (!TrySplit(target, 1, ' ', out target, out externAlias))
                            {
                                return false;
                            }

                            return true;

                        default:
                            return false;
                    }

                case 'X': // C# extern alias (in file)
                    externAlias = null;
                    alias = import.Substring(1); // For consistency with the portable format, store it in alias, rather than externAlias.
                    target = null;
                    kind = ImportTargetKind.Assembly;
                    return true;

                case 'Z': // C# extern alias (module-level)
                    // For consistency with the portable format, store it in alias, rather than externAlias.
                    if (!TrySplit(import, 1, ' ', out alias, out target))
                    {
                        return false;
                    }

                    externAlias = null;
                    kind = ImportTargetKind.Assembly;
                    return true;

                default:
                    return false;
            }
        }
Exemple #7
0
 public ImportTarget(ImportTargetKind kind)
 {
     this.kind = kind;
 }
Exemple #8
0
        /// <summary>
        /// Parse a string representing a VB import statement.
        /// </summary>
        /// <exception cref="ArgumentNullException"><paramref name="import"/> is null.</exception>
        /// <exception cref="ArgumentException">Format of <paramref name="import"/> is not valid.</exception>
        public static bool TryParseVisualBasicImportString(string import, out string alias, out string target, out ImportTargetKind kind, out ImportScope scope)
        {
            alias  = null;
            target = null;
            kind   = default(ImportTargetKind);
            scope  = default(ImportScope);

            if (import == null)
            {
                return(false);
            }

            // VB current namespace
            if (import.Length == 0)
            {
                alias  = null;
                target = import;
                kind   = ImportTargetKind.CurrentNamespace;
                scope  = ImportScope.Unspecified;
                return(true);
            }

            int pos = 0;

            switch (import[pos])
            {
            case '&':
            // Indicates the presence of embedded PIA types from a given assembly.  No longer required (as of Roslyn).
            case '$':
            case '#':
                // From ProcedureContext::LoadImportsAndDefaultNamespaceNormal:
                //   "Module Imports and extension types are no longer needed since we are not doing custom name lookup"
                alias  = null;
                target = import;
                kind   = ImportTargetKind.Defunct;
                scope  = ImportScope.Unspecified;
                return(true);

            case '*':     // VB default namespace
                // see PEBuilder.cpp in vb\language\CodeGen
                pos++;
                alias  = null;
                target = import.Substring(pos);
                kind   = ImportTargetKind.DefaultNamespace;
                scope  = ImportScope.Unspecified;
                return(true);

            case '@':     // VB cases other than default and current namespace
                // see PEBuilder.cpp in vb\language\CodeGen
                pos++;
                if (pos >= import.Length)
                {
                    return(false);
                }

                scope = ImportScope.Unspecified;
                switch (import[pos])
                {
                case 'F':
                    scope = ImportScope.File;
                    pos++;
                    break;

                case 'P':
                    scope = ImportScope.Project;
                    pos++;
                    break;
                }

                if (pos >= import.Length)
                {
                    return(false);
                }

                switch (import[pos])
                {
                case 'A':
                    pos++;

                    if (import[pos] != ':')
                    {
                        return(false);
                    }

                    pos++;

                    if (!TrySplit(import, pos, '=', out alias, out target))
                    {
                        return(false);
                    }

                    kind = ImportTargetKind.NamespaceOrType;
                    return(true);

                case 'X':
                    pos++;

                    if (import[pos] != ':')
                    {
                        return(false);
                    }

                    pos++;

                    if (!TrySplit(import, pos, '=', out alias, out target))
                    {
                        return(false);
                    }

                    kind = ImportTargetKind.XmlNamespace;
                    return(true);

                case 'T':
                    pos++;

                    if (import[pos] != ':')
                    {
                        return(false);
                    }

                    pos++;

                    alias  = null;
                    target = import.Substring(pos);
                    kind   = ImportTargetKind.Type;
                    return(true);

                case ':':
                    pos++;
                    alias  = null;
                    target = import.Substring(pos);
                    kind   = ImportTargetKind.Namespace;
                    return(true);

                default:
                    alias  = null;
                    target = import.Substring(pos);
                    kind   = ImportTargetKind.MethodToken;
                    return(true);
                }

            default:
                // VB current namespace
                alias  = null;
                target = import;
                kind   = ImportTargetKind.CurrentNamespace;
                scope  = ImportScope.Unspecified;
                return(true);
            }
        }
Exemple #9
0
        /// <summary>
        /// Parse a string representing a C# using (or extern alias) directive.
        /// </summary>
        /// <remarks>
        /// <![CDATA[
        /// For C#:
        ///  "USystem" -> <namespace name="System" />
        ///  "AS USystem" -> <alias name="S" target="System" kind="namespace" />
        ///  "AC TSystem.Console" -> <alias name="C" target="System.Console" kind="type" />
        ///  "AS ESystem alias" -> <alias name="S" qualifier="alias" target="System" kind="type" />
        ///  "XOldLib" -> <extern alias="OldLib" />
        ///  "ZOldLib assembly" -> <externinfo name="OldLib" assembly="assembly" />
        ///  "ESystem alias" -> <namespace qualifier="alias" name="System" />
        ///  "TSystem.Math" -> <type name="System.Math" />
        /// ]]>
        /// </remarks>
        public static bool TryParseCSharpImportString(string import, out string alias, out string externAlias, out string target, out ImportTargetKind kind)
        {
            alias       = null;
            externAlias = null;
            target      = null;
            kind        = default(ImportTargetKind);

            if (string.IsNullOrEmpty(import))
            {
                return(false);
            }

            switch (import[0])
            {
            case 'U':     // C# (namespace) using
                alias       = null;
                externAlias = null;
                target      = import.Substring(1);
                kind        = ImportTargetKind.Namespace;
                return(true);

            case 'E':     // C# (namespace) using
                // NOTE: Dev12 has related cases "I" and "O" in EMITTER::ComputeDebugNamespace,
                // but they were probably implementation details that do not affect roslyn.
                if (!TrySplit(import, 1, ' ', out target, out externAlias))
                {
                    return(false);
                }

                alias = null;
                kind  = ImportTargetKind.Namespace;
                return(true);

            case 'T':     // C# (type) using
                alias       = null;
                externAlias = null;
                target      = import.Substring(1);
                kind        = ImportTargetKind.Type;
                return(true);

            case 'A':     // C# type or namespace alias
                if (!TrySplit(import, 1, ' ', out alias, out target))
                {
                    return(false);
                }

                switch (target[0])
                {
                case 'U':
                    kind        = ImportTargetKind.Namespace;
                    target      = target.Substring(1);
                    externAlias = null;
                    return(true);

                case 'T':
                    kind        = ImportTargetKind.Type;
                    target      = target.Substring(1);
                    externAlias = null;
                    return(true);

                case 'E':
                    kind = ImportTargetKind.Namespace;         // Never happens for types.
                    if (!TrySplit(target, 1, ' ', out target, out externAlias))
                    {
                        return(false);
                    }

                    return(true);

                default:
                    return(false);
                }

            case 'X':                              // C# extern alias (in file)
                externAlias = null;
                alias       = import.Substring(1); // For consistency with the portable format, store it in alias, rather than externAlias.
                target      = null;
                kind        = ImportTargetKind.Assembly;
                return(true);

            case 'Z':     // C# extern alias (module-level)
                // For consistency with the portable format, store it in alias, rather than externAlias.
                if (!TrySplit(import, 1, ' ', out alias, out target))
                {
                    return(false);
                }

                externAlias = null;
                kind        = ImportTargetKind.Assembly;
                return(true);

            default:
                return(false);
            }
        }
        private static void ReadVisualBasicImportsDebugInfo(
            ISymUnmanagedReader reader,
            int methodToken,
            int methodVersion,
            out ImmutableArray <ImmutableArray <ImportRecord> > importRecordGroups,
            out string defaultNamespaceName)
        {
            importRecordGroups = ImmutableArray <ImmutableArray <ImportRecord> > .Empty;

            var importStrings = CustomDebugInfoReader.GetVisualBasicImportStrings(
                methodToken,
                KeyValuePair.Create(reader, methodVersion),
                (token, arg) => GetImportStrings(arg.Key, token, arg.Value));

            if (importStrings.IsDefault)
            {
                defaultNamespaceName = "";
                return;
            }

            defaultNamespaceName = null;
            var projectLevelImportRecords = ArrayBuilder <ImportRecord> .GetInstance();

            var fileLevelImportRecords = ArrayBuilder <ImportRecord> .GetInstance();

            foreach (string importString in importStrings)
            {
                Debug.Assert(importString != null);

                if (importString.Length > 0 && importString[0] == '*')
                {
                    string            alias  = null;
                    string            target = null;
                    ImportTargetKind  kind   = 0;
                    VBImportScopeKind scope  = 0;

                    if (!CustomDebugInfoReader.TryParseVisualBasicImportString(importString, out alias, out target, out kind, out scope))
                    {
                        Debug.WriteLine($"Unable to parse import string '{importString}'");
                        continue;
                    }
                    else if (kind == ImportTargetKind.Defunct)
                    {
                        continue;
                    }

                    Debug.Assert(alias == null); // The default namespace is never aliased.
                    Debug.Assert(target != null);
                    Debug.Assert(kind == ImportTargetKind.DefaultNamespace);

                    // We only expect to see one of these, but it looks like ProcedureContext::LoadImportsAndDefaultNamespaceNormal
                    // implicitly uses the last one if there are multiple.
                    Debug.Assert(defaultNamespaceName == null);

                    defaultNamespaceName = target;
                }
                else
                {
                    ImportRecord      importRecord;
                    VBImportScopeKind scope = 0;

                    if (TryCreateImportRecordFromVisualBasicImportString(importString, out importRecord, out scope))
                    {
                        if (scope == VBImportScopeKind.Project)
                        {
                            projectLevelImportRecords.Add(importRecord);
                        }
                        else
                        {
                            Debug.Assert(scope == VBImportScopeKind.File || scope == VBImportScopeKind.Unspecified);
                            fileLevelImportRecords.Add(importRecord);
                        }
                    }
                    else
                    {
                        Debug.WriteLine($"Failed to parse import string {importString}");
                    }
                }
            }

            importRecordGroups = ImmutableArray.Create(
                fileLevelImportRecords.ToImmutableAndFree(),
                projectLevelImportRecords.ToImmutableAndFree());

            defaultNamespaceName = defaultNamespaceName ?? "";
        }
        /// <summary>
        /// Parse a string representing a VB import statement.
        /// </summary>
        /// <exception cref="ArgumentNullException"><paramref name="import"/> is null.</exception>
        /// <exception cref="ArgumentException">Format of <paramref name="import"/> is not valid.</exception>
        public static void ParseVisualBasicImportString(string import, out string alias, out string target, out ImportTargetKind kind, out ImportScope scope)
        {
            if (import == null)
            {
                throw new ArgumentNullException("import");
            }

            if (import.Length == 0) // VB current namespace
            {
                alias  = null;
                target = import;
                kind   = ImportTargetKind.CurrentNamespace;
                scope  = ImportScope.Unspecified;
                return;
            }

            int pos = 0;

            switch (import[pos])
            {
            case '*':     // VB default namespace
                // see PEBuilder.cpp in vb\language\CodeGen
                pos++;
                alias  = null;
                target = import.Substring(pos);
                kind   = ImportTargetKind.DefaultNamespace;
                scope  = ImportScope.Unspecified;
                return;

            case '@':     // VB cases other than default and current namespace
                // see PEBuilder.cpp in vb\language\CodeGen
                pos++;
                if (pos >= import.Length)
                {
                    throw new ArgumentException(import, "import");
                }

                scope = ImportScope.Unspecified;
                switch (import[pos])
                {
                case 'F':
                    scope = ImportScope.File;
                    pos++;
                    break;

                case 'P':
                    scope = ImportScope.Project;
                    pos++;
                    break;
                }

                if (pos >= import.Length)
                {
                    throw new ArgumentException(import, "import");
                }

                switch (import[pos])
                {
                case 'A':
                    pos++;
                    if (import[pos] != ':')
                    {
                        throw new ArgumentException(import, "import");
                    }
                    pos++;

                    if (!TrySplit(import, pos, '=', out alias, out target))
                    {
                        throw new ArgumentException(import, "import");
                    }

                    kind = ImportTargetKind.NamespaceOrType;
                    return;

                case 'X':
                    pos++;
                    if (import[pos] != ':')
                    {
                        throw new ArgumentException(import, "import");
                    }
                    pos++;

                    if (!TrySplit(import, pos, '=', out alias, out target))
                    {
                        throw new ArgumentException(import, "import");
                    }

                    kind = ImportTargetKind.XmlNamespace;
                    return;

                case 'T':
                    pos++;
                    if (import[pos] != ':')
                    {
                        throw new ArgumentException(import, "import");
                    }
                    pos++;

                    alias  = null;
                    target = import.Substring(pos);
                    kind   = ImportTargetKind.Type;
                    return;

                case ':':
                    pos++;
                    alias  = null;
                    target = import.Substring(pos);
                    kind   = ImportTargetKind.Namespace;
                    return;

                default:
                    alias  = null;
                    target = import.Substring(pos);
                    kind   = ImportTargetKind.MethodToken;
                    return;
                }

            default:     // VB current namespace
                alias  = null;
                target = import;
                kind   = ImportTargetKind.CurrentNamespace;
                scope  = ImportScope.Unspecified;
                return;
            }
        }
        /// <summary>
        /// Parse a string representing a C# using (or extern alias) directive.
        /// </summary>
        /// <remarks>
        /// <![CDATA[
        /// For C#:
        ///  "USystem" -> <namespace name="System" />
        ///  "AS USystem" -> <alias name="S" target="System" kind="namespace" />
        ///  "AC TSystem.Console" -> <alias name="C" target="System.Console" kind="type" />
        ///  "AS ESystem alias" -> <alias name="S" qualifier="alias" target="System" kind="type" />
        ///  "XOldLib" -> <extern alias="OldLib" />
        ///  "ZOldLib assembly" -> <externinfo name="OldLib" assembly="assembly" />
        ///  "ESystem alias" -> <namespace qualifier="alias" name="System" />
        /// ]]>
        /// </remarks>
        public static void ParseCSharpImportString(string import, out string alias, out string externAlias, out string target, out ImportTargetKind kind)
        {
            if (import == null)
            {
                throw new ArgumentNullException("import");
            }

            if (import.Length == 0)
            {
                throw new ArgumentException(import, "import");
            }

            switch (import[0])
            {
            case 'U':     // C# using
                alias       = null;
                externAlias = null;
                target      = import.Substring(1);
                kind        = ImportTargetKind.Namespace;
                return;

            case 'E':     // C# using
                // NOTE: Dev12 has related cases "I" and "O" in EMITTER::ComputeDebugNamespace,
                // but they were probably implementation details that do not affect roslyn.
                if (!TrySplit(import, 1, ' ', out target, out externAlias))
                {
                    throw new ArgumentException(import, "import");
                }

                alias = null;
                kind  = ImportTargetKind.Namespace;
                return;

            case 'A':     // C# type or namespace alias
                if (!TrySplit(import, 1, ' ', out alias, out target))
                {
                    throw new ArgumentException(import, "import");
                }

                switch (target[0])
                {
                case 'U':
                    kind        = ImportTargetKind.Namespace;
                    target      = target.Substring(1);
                    externAlias = null;
                    return;

                case 'T':
                    kind        = ImportTargetKind.Type;
                    target      = target.Substring(1);
                    externAlias = null;
                    return;

                case 'E':
                    kind = ImportTargetKind.Namespace;         // Never happens for types.
                    if (!TrySplit(target, 1, ' ', out target, out externAlias))
                    {
                        throw new ArgumentException(import, "import");
                    }
                    return;

                default:
                    throw new ArgumentException(import, "import");
                }

            case 'X':     // C# extern alias (in file)
                externAlias = import.Substring(1);
                alias       = null;
                target      = null;
                kind        = ImportTargetKind.Assembly;
                return;

            case 'Z':     // C# extern alias (module-level)
                if (!TrySplit(import, 1, ' ', out externAlias, out target))
                {
                    throw new ArgumentException(import, "import");
                }

                alias = null;
                kind  = ImportTargetKind.Assembly;
                return;

            default:
                throw new ArgumentException(import, "import");
            }
        }
Exemple #13
0
 public ImportTarget(ImportTargetKind kind)
 {
     this.kind = kind;
 }
        /// <summary>
        /// Parse a string representing a VB import statement.
        /// </summary>
        /// <exception cref="ArgumentNullException"><paramref name="import"/> is null.</exception>
        /// <exception cref="ArgumentException">Format of <paramref name="import"/> is not valid.</exception>
        public static bool TryParseVisualBasicImportString(string import, out string alias, out string target, out ImportTargetKind kind, out ImportScope scope)
        {
            alias = null;
            target = null;
            kind = default(ImportTargetKind);
            scope = default(ImportScope);

            if (import == null)
            {
                return false;
            }

            if (import.Length == 0) // VB current namespace
            {
                alias = null;
                target = import;
                kind = ImportTargetKind.CurrentNamespace;
                scope = ImportScope.Unspecified;
                return true;
            }

            // TODO (acasey): looks like we missed some cases (e.g. '$', '#', '&')
            // See ProcedureContext::LoadImportsAndDefaultNamespaceNormal.

            int pos = 0;
            switch (import[pos])
            {
                case '*': // VB default namespace
                    // see PEBuilder.cpp in vb\language\CodeGen
                    pos++;
                    alias = null;
                    target = import.Substring(pos);
                    kind = ImportTargetKind.DefaultNamespace;
                    scope = ImportScope.Unspecified;
                    return true;
                case '@': // VB cases other than default and current namespace
                    // see PEBuilder.cpp in vb\language\CodeGen
                    pos++;
                    if (pos >= import.Length)
                    {
                        return false;
                    }

                    scope = ImportScope.Unspecified;
                    switch (import[pos])
                    {
                        case 'F':
                            scope = ImportScope.File;
                            pos++;
                            break;
                        case 'P':
                            scope = ImportScope.Project;
                            pos++;
                            break;
                    }

                    if (pos >= import.Length)
                    {
                        return false;
                    }

                    switch (import[pos])
                    {
                        case 'A':
                            pos++;
                            if (import[pos] != ':')
                            {
                                return false;
                            }
                            pos++;

                            if (!TrySplit(import, pos, '=', out alias, out target))
                            {
                                return false;
                            }

                            kind = ImportTargetKind.NamespaceOrType;
                            return true;
                        case 'X':
                            pos++;
                            if (import[pos] != ':')
                            {
                                return false;
                            }
                            pos++;

                            if (!TrySplit(import, pos, '=', out alias, out target))
                            {
                                return false;
                            }

                            kind = ImportTargetKind.XmlNamespace;
                            return true;
                        case 'T':
                            pos++;
                            if (import[pos] != ':')
                            {
                                return false;
                            }
                            pos++;

                            alias = null;
                            target = import.Substring(pos);
                            kind = ImportTargetKind.Type;
                            return true;
                        case ':':
                            pos++;
                            alias = null;
                            target = import.Substring(pos);
                            kind = ImportTargetKind.Namespace;
                            return true;
                        default:
                            alias = null;
                            target = import.Substring(pos);
                            kind = ImportTargetKind.MethodToken;
                            return true;
                    }
                default: // VB current namespace
                    alias = null;
                    target = import;
                    kind = ImportTargetKind.CurrentNamespace;
                    scope = ImportScope.Unspecified;
                    return true;
            }
        }
        /// <summary>
        /// Parse a string representing a VB import statement.
        /// </summary>
        /// <exception cref="ArgumentNullException"><paramref name="import"/> is null.</exception>
        /// <exception cref="ArgumentException">Format of <paramref name="import"/> is not valid.</exception>
        public static bool TryParseVisualBasicImportString(string import, out string alias, out string target, out ImportTargetKind kind, out ImportScope scope)
        {
            alias  = null;
            target = null;
            kind   = default(ImportTargetKind);
            scope  = default(ImportScope);

            if (import == null)
            {
                return(false);
            }

            if (import.Length == 0) // VB current namespace
            {
                alias  = null;
                target = import;
                kind   = ImportTargetKind.CurrentNamespace;
                scope  = ImportScope.Unspecified;
                return(true);
            }

            // TODO (acasey): looks like we missed some cases (e.g. '$', '#', '&')
            // See ProcedureContext::LoadImportsAndDefaultNamespaceNormal.

            int pos = 0;

            switch (import[pos])
            {
            case '*':     // VB default namespace
                // see PEBuilder.cpp in vb\language\CodeGen
                pos++;
                alias  = null;
                target = import.Substring(pos);
                kind   = ImportTargetKind.DefaultNamespace;
                scope  = ImportScope.Unspecified;
                return(true);

            case '@':     // VB cases other than default and current namespace
                // see PEBuilder.cpp in vb\language\CodeGen
                pos++;
                if (pos >= import.Length)
                {
                    return(false);
                }

                scope = ImportScope.Unspecified;
                switch (import[pos])
                {
                case 'F':
                    scope = ImportScope.File;
                    pos++;
                    break;

                case 'P':
                    scope = ImportScope.Project;
                    pos++;
                    break;
                }

                if (pos >= import.Length)
                {
                    return(false);
                }

                switch (import[pos])
                {
                case 'A':
                    pos++;
                    if (import[pos] != ':')
                    {
                        return(false);
                    }
                    pos++;

                    if (!TrySplit(import, pos, '=', out alias, out target))
                    {
                        return(false);
                    }

                    kind = ImportTargetKind.NamespaceOrType;
                    return(true);

                case 'X':
                    pos++;
                    if (import[pos] != ':')
                    {
                        return(false);
                    }
                    pos++;

                    if (!TrySplit(import, pos, '=', out alias, out target))
                    {
                        return(false);
                    }

                    kind = ImportTargetKind.XmlNamespace;
                    return(true);

                case 'T':
                    pos++;
                    if (import[pos] != ':')
                    {
                        return(false);
                    }
                    pos++;

                    alias  = null;
                    target = import.Substring(pos);
                    kind   = ImportTargetKind.Type;
                    return(true);

                case ':':
                    pos++;
                    alias  = null;
                    target = import.Substring(pos);
                    kind   = ImportTargetKind.Namespace;
                    return(true);

                default:
                    alias  = null;
                    target = import.Substring(pos);
                    kind   = ImportTargetKind.MethodToken;
                    return(true);
                }

            default:     // VB current namespace
                alias  = null;
                target = import;
                kind   = ImportTargetKind.CurrentNamespace;
                scope  = ImportScope.Unspecified;
                return(true);
            }
        }