private bool AddImportDef(
            ProtocolDescriptor.ProtocolDef protoDef, XElement element,
            ProtocolDescriptor.ProtocolDef externalProtoDef)
        {
            ProtocolDescriptor.ImportDef def =
                new ProtocolDescriptor.ImportDef();
            def.ParentRef  = protoDef;
            def.Name       = externalProtoDef.Name;
            def.LineNumber = GetLineNumber(element);
            def.ProtoDef   = externalProtoDef;

            if (protoDef.ImportNameIndex.ContainsKey(def.Name))
            {
                PrintLineError(protoDef, element,
                               "import `{0}` duplicated", def.Name);
                return(false);
            }

            protoDef.Imports.Add(def);
            protoDef.ImportNameIndex.Add(def.Name, def);

            return(true);
        }
        private void ProcessImportedProtocols(
            ProtocolDescriptor.ProtocolDef protoDef)
        {
            Dictionary <string, ProtocolDescriptor.ProtocolDef> usedProtos =
                new Dictionary <string, ProtocolDescriptor.ProtocolDef>();
            Dictionary <string, ProtocolDescriptor.ProtocolDef> enumRefProtos =
                new Dictionary <string, ProtocolDescriptor.ProtocolDef>();
            Dictionary <string, ProtocolDescriptor.ProtocolDef> structRefProtos =
                new Dictionary <string, ProtocolDescriptor.ProtocolDef>();
            Dictionary <string, ProtocolDescriptor.ProtocolDef> enumMapRefProtos =
                new Dictionary <string, ProtocolDescriptor.ProtocolDef>();

            // collect enum ref protocols
            for (int i = 0; i < protoDef.Enums.Count; ++i)
            {
                ProtocolDescriptor.EnumDef enumDef =
                    protoDef.Enums[i];

                for (int j = 0; j < enumDef.Items.Count; ++j)
                {
                    ProtocolDescriptor.EnumDef.ItemDef def =
                        enumDef.Items[j];
                    if (def.RefEnumItemDef != null)
                    {
                        ProtocolDescriptor.ProtocolDef refProtoDef =
                            def.RefEnumItemDef.ParentRef.ParentRef;
                        usedProtos[refProtoDef.Name]    = refProtoDef;
                        enumRefProtos[refProtoDef.Name] = refProtoDef;
                    }
                }
            }

            // collect struct ref protocols
            for (int i = 0; i < protoDef.Structs.Count; ++i)
            {
                ProtocolDescriptor.StructDef structDef =
                    protoDef.Structs[i];

                for (int j = 0; j < structDef.Fields.Count; ++j)
                {
                    ProtocolDescriptor.StructDef.FieldDef def =
                        structDef.Fields[j];
                    if (def.RefEnumDef != null)
                    {
                        ProtocolDescriptor.ProtocolDef refProtoDef =
                            def.RefEnumDef.ParentRef;
                        usedProtos[refProtoDef.Name]      = refProtoDef;
                        structRefProtos[refProtoDef.Name] = refProtoDef;
                    }
                    if (def.RefStructDef != null)
                    {
                        ProtocolDescriptor.ProtocolDef refProtoDef =
                            def.RefStructDef.ParentRef;
                        usedProtos[refProtoDef.Name]      = refProtoDef;
                        structRefProtos[refProtoDef.Name] = refProtoDef;
                    }
                }
            }

            // collect enum map ref protocols
            for (int i = 0; i < protoDef.EnumMaps.Count; ++i)
            {
                ProtocolDescriptor.EnumMapDef enumMapDef =
                    protoDef.EnumMaps[i];

                for (int j = 0; j < enumMapDef.Items.Count; ++j)
                {
                    ProtocolDescriptor.EnumMapDef.ItemDef def =
                        enumMapDef.Items[j];
                    if (def.RefEnumItemDef != null)
                    {
                        ProtocolDescriptor.ProtocolDef refProtoDef =
                            def.RefEnumItemDef.ParentRef.ParentRef;
                        usedProtos[refProtoDef.Name]       = refProtoDef;
                        enumMapRefProtos[refProtoDef.Name] = refProtoDef;
                    }
                    if (def.RefStructDef != null)
                    {
                        ProtocolDescriptor.ProtocolDef refProtoDef =
                            def.RefStructDef.ParentRef;
                        usedProtos[refProtoDef.Name]       = refProtoDef;
                        enumMapRefProtos[refProtoDef.Name] = refProtoDef;
                    }
                }
            }

            for (int i = 0; i < protoDef.Imports.Count; ++i)
            {
                ProtocolDescriptor.ImportDef importDef =
                    protoDef.Imports[i];

                // check imported protocol is used
                if (usedProtos.ContainsKey(importDef.ProtoDef.Name) == false)
                {
                    Console.Error.WriteLine(string.Format(
                                                "warning:{0}:{1}: protocol `{2}` " +
                                                "is not used but imported",
                                                protoDef.FilePath, importDef.LineNumber,
                                                importDef.Name));
                }

                if (enumRefProtos.ContainsKey(importDef.ProtoDef.Name))
                {
                    importDef.IsRefByEnum = true;
                }
                if (structRefProtos.ContainsKey(importDef.ProtoDef.Name))
                {
                    importDef.IsRefByStruct = true;
                }
                if (enumMapRefProtos.ContainsKey(importDef.ProtoDef.Name))
                {
                    importDef.IsRefByEnumMap = true;
                }
            }
        }