Пример #1
0
        internal static DefinitionMapData GetDefinitionMapData(ProjectItem projectItem)
        {
            // Initialize our result
            DefinitionMapData result = null;

            // Try to find our map data for the typescript definition file
            ProjectItem definitionMapProjectItem = projectItem.ProjectItems
                                                   .Cast <ProjectItem>()
                                                   .Where(pi => pi.Name == GenerationService.GenerateFileName(projectItem.Name) + ".map")
                                                   .FirstOrDefault();

            // Continue if found
            if (definitionMapProjectItem != null)
            {
                // Get the text of our mapping file
                string documentText = VSHelpers.GetDocumentText(definitionMapProjectItem);

                // Continue if the document has text
                if (string.IsNullOrWhiteSpace(documentText) == false)
                {
                    // Try to parse the containing json string
                    // When a SerializationException is getting thrown the document text wasn't valid
                    try
                    {
                        result = JsonConvert.DeserializeObject <DefinitionMapData>(documentText);
                    }
                    catch (JsonSerializationException) { }
                }
            }

            return(result);
        }
Пример #2
0
 public static string ConvertToTypeScript(ProjectItem sourceItem)
 {
     try
     {
         Options.ReadOptionOverrides(sourceItem);
         VSHelpers.WriteOnOutputWindow(string.Format("{0} - Started", sourceItem.Name));
         var list = IntellisenseParser.ProcessFile(sourceItem);
         // path is needed for relative paths of imports
         var sourceItemPath = sourceItem.Properties.Item("FullPath").Value as string;
         VSHelpers.WriteOnOutputWindow(string.Format("{0} - Completed", sourceItem.Name));
         return(IntellisenseWriter.WriteTypeScript(list.ToList(), sourceItemPath));
     }
     catch (Exception ex)
     {
         VSHelpers.WriteOnOutputWindow(string.Format("{0} - Failure", sourceItem.Name));
         if (ex is ExceptionForUser)
         {
             // "expected" exception, show to user instead of reporting
             VSHelpers.WriteOnOutputWindow(ex.Message);
         }
         else
         {
             Telemetry.TrackException("ParseFailure", ex);
         }
         return(null);
     }
 }
Пример #3
0
        private static IntellisenseType GetType(CodeClass rootElement, CodeTypeRef codeTypeRef, HashSet <string> traversedTypes, HashSet <string> references)
        {
            var isArray      = codeTypeRef.TypeKind == vsCMTypeRef.vsCMTypeRefArray;
            var isCollection = codeTypeRef.AsString.StartsWith("System.Collections", StringComparison.Ordinal);
            var isDictionary = false;

            var effectiveTypeRef = codeTypeRef;

            if (isArray && codeTypeRef.ElementType != null)
            {
                effectiveTypeRef = effectiveTypeRef.ElementType;
            }
            else if (isCollection)
            {
                effectiveTypeRef = TryToGuessGenericArgument(rootElement, effectiveTypeRef);
            }

            if (isCollection)
            {
                isDictionary = codeTypeRef.AsString.StartsWith("System.Collections.Generic.Dictionary", StringComparison.Ordinal) ||
                               codeTypeRef.AsString.StartsWith("System.Collections.Generic.IDictionary", StringComparison.Ordinal);
            }

            string typeName = effectiveTypeRef.AsFullName;

            try
            {
                var codeClass   = effectiveTypeRef.CodeType as CodeClass2;
                var codeEnum    = effectiveTypeRef.CodeType as CodeEnum;
                var isPrimitive = IsPrimitive(effectiveTypeRef);

                var result = new IntellisenseType
                {
                    IsArray                 = !isDictionary && (isArray || isCollection),
                    IsDictionary            = isDictionary,
                    CodeName                = effectiveTypeRef.AsString,
                    ClientSideReferenceName =
                        effectiveTypeRef.TypeKind == vsCMTypeRef.vsCMTypeRefCodeType &&
                        effectiveTypeRef.CodeType.InfoLocation == vsCMInfoLocation.vsCMInfoLocationProject
                        ?
                        (codeClass != null && HasIntellisense(codeClass.ProjectItem, references) ? (GetNamespace(codeClass) + "." + Utility.CamelCaseClassName(GetClassName(codeClass))) : null) ??
                        (codeEnum != null && HasIntellisense(codeEnum.ProjectItem, references) ? (GetNamespace(codeEnum) + "." + Utility.CamelCaseClassName(codeEnum.Name)) : null)
                        : null
                };

                if (!isPrimitive && codeClass != null && !traversedTypes.Contains(effectiveTypeRef.CodeType.FullName) && !isCollection)
                {
                    traversedTypes.Add(effectiveTypeRef.CodeType.FullName);
                    result.Shape = GetProperties(effectiveTypeRef.CodeType.Members, traversedTypes, references).ToList();
                    traversedTypes.Remove(effectiveTypeRef.CodeType.FullName);
                }

                return(result);
            }
            catch (InvalidCastException)
            {
                VSHelpers.WriteOnOutputWindow(string.Format("ERROR - Cannot find definition for {0}", typeName));
                throw new ArgumentException(string.Format("Cannot find definition of {0}", typeName));
            }
        }
        public static string ConvertToTypeScriptEnumsOnly(ProjectItem sourceItem, ref DefinitionMapData definitionMapData, out bool isEmpty)
        {
            try
            {
                // Initialize the definition data if there was no specified
                if (definitionMapData == null)
                {
                    definitionMapData = new DefinitionMapData();
                }

                Options.ReadOptionOverrides(sourceItem);
                VSHelpers.WriteOnOutputWindow(string.Format("{0} - Started (enums only)", sourceItem.Name));
                var list = IntellisenseParser.ProcessFile(sourceItem, definitionMapData);
                VSHelpers.WriteOnOutputWindow(string.Format("{0} - Completed", sourceItem.Name));
                return(IntellisenseWriter.WriteTypeScriptEnumsOnly(list, sourceItem, out isEmpty));
            }
            catch (Exception ex)
            {
                isEmpty = true;

                VSHelpers.WriteOnOutputWindow(string.Format("{0} - Failure", sourceItem.Name));
                Telemetry.TrackException("ParseFailure", ex);
                return(null);
            }
        }
        public static void CreateDtsMapFile(ProjectItem sourceItem, DefinitionMapData definitionMapData)
        {
            string sourceFile = sourceItem.FileNames[1];
            string dtsFile    = GenerationService.GenerateFileName(sourceFile) + ".map";

            VSHelpers.CheckFileOutOfSourceControl(dtsFile);
            File.WriteAllText(dtsFile, JsonConvert.SerializeObject(definitionMapData, Formatting.Indented));

            if (sourceItem.ContainingProject.IsKind(ProjectTypes.DOTNET_Core, ProjectTypes.ASPNET_5))
            {
                Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() =>
                {
                    var dtsItem = VSHelpers.GetProjectItem(dtsFile);

                    if (dtsItem != null)
                    {
                        dtsItem.Properties.Item("DependentUpon").Value = sourceItem.Name;
                    }

                    Telemetry.TrackOperation("FileGenerated");
                }), DispatcherPriority.ApplicationIdle, null);
            }
            else if (sourceItem.ContainingProject.IsKind(ProjectTypes.WEBSITE_PROJECT))
            {
                sourceItem.ContainingProject.ProjectItems.AddFromFile(dtsFile);
            }
            else
            {
                sourceItem.ProjectItems.AddFromFile(dtsFile);
            }
        }
        public static void CopyDtsFile(DefinitionMapData definitionMapData, ProjectItem projectItem, string dts, bool isEnumDefinition)
        {
            // There might be paths where this file should be copied to
            foreach (string copyPath in definitionMapData.CopyPaths)
            {
                // Ignore empty paths
                if (string.IsNullOrWhiteSpace(copyPath))
                {
                    continue;
                }

                // Get the path from our project item and combine it with the target path and target name
                string filePath = Path.GetFullPath(Path.Combine(
                                                       Path.GetDirectoryName(projectItem.FileNames[1]),
                                                       copyPath,
                                                       GenerationService.GetCopyDtsFileName(definitionMapData, projectItem, isEnumDefinition)));

                // Try to write our definition file to the new path too
                try
                {
                    File.WriteAllText(filePath, dts);
                    VSHelpers.WriteOnOutputWindow($"File written to \"{filePath}\"");
                }
                catch (Exception ex)
                {
                    VSHelpers.WriteOnOutputWindow($"Could not write file to \"{filePath}\"{Environment.NewLine}" +
                                                  $"Reason: {ex.Message}");
                }
            }
        }
Пример #7
0
        private static List <string> GetReferences(IEnumerable <IntellisenseObject> objects, ProjectItem sourceItem)
        {
            if (Options.KeepReferencesUnchanged)
            {
                ProjectItem generatedProjectItem = sourceItem.ProjectItems
                                                   .Cast <ProjectItem>()
                                                   .Where(item => GenerationService.GenerateFileName(sourceItem.Name) == item.Name)
                                                   .FirstOrDefault();

                if (generatedProjectItem != null)
                {
                    string documentText = VSHelpers.GetDocumentText(generatedProjectItem);

                    if (string.IsNullOrWhiteSpace(documentText) == false)
                    {
                        string pattern = "/// <reference path=\"(.*)\" />\r\n";
                        return(new Regex(pattern).Matches(documentText)
                               .Cast <Match>()
                               .Select(m => m.Groups[1].Value)
                               .OrderBy(r => r)
                               .ToList());
                    }
                }
            }

            return(objects
                   .SelectMany(o => o.References)
                   .Where(r => Path.GetFileName(r) != GenerationService.GenerateFileName(sourceItem.Name))
                   .Distinct()
                   .OrderBy(r => r)
                   .ToList());
        }
Пример #8
0
        public static void CreateDtsFile(ProjectItem sourceItem)
        {
            string sourceFile = sourceItem.FileNames[1];
            string dtsFile    = Utility.GenerateFileName(sourceFile);
            string dts        = ConvertToTypeScript(sourceItem);

            VSHelpers.CheckFileOutOfSourceControl(dtsFile);
            File.WriteAllText(dtsFile, dts);

            if (sourceItem.ContainingProject.IsKind(ProjectTypes.DOTNET_Core, ProjectTypes.ASPNET_5))
            {
                Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() =>
                {
                    var dtsItem = VSHelpers.GetProjectItem(dtsFile);

                    if (dtsItem != null)
                    {
                        dtsItem.Properties.Item("DependentUpon").Value = sourceItem.Name;
                    }

                    Telemetry.TrackOperation("FileGenerated");
                }), DispatcherPriority.ApplicationIdle, null);
            }
            else if (sourceItem.ContainingProject.IsKind(ProjectTypes.WEBSITE_PROJECT))
            {
                sourceItem.ContainingProject.ProjectItems.AddFromFile(dtsFile);
            }
        }
        public static void CreateDtsFile(ProjectItem sourceItem)
        {
            string sourceFile  = sourceItem.FileNames[1];
            string dtsFile     = GenerationService.GenerateFileName(sourceFile);
            string dtsEnumFile = GenerationService.GenerateFileName(sourceFile);

            // Get metadata from our project item
            DefinitionMapData definitionMapData = VSHelpers.GetDefinitionMapData(sourceItem);

            string dts         = ConvertToTypeScriptWithoutEnums(sourceItem, ref definitionMapData, out bool isEmpty);
            string dtsEnumOnly = ConvertToTypeScriptEnumsOnly(sourceItem, ref definitionMapData, out bool isEmptyEnum);

            VSHelpers.CheckFileOutOfSourceControl(dtsFile);
            File.WriteAllText(dtsFile, dts);

            if (isEmptyEnum == false)
            {
                File.WriteAllText(dtsEnumFile, dtsEnumOnly);
            }

            if (sourceItem.ContainingProject.IsKind(ProjectTypes.DOTNET_Core, ProjectTypes.ASPNET_5))
            {
                Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() =>
                {
                    var dtsItem = VSHelpers.GetProjectItem(dtsFile);

                    if (dtsItem != null)
                    {
                        dtsItem.Properties.Item("DependentUpon").Value = sourceItem.Name;
                    }

                    if (isEmptyEnum == false)
                    {
                        var dtsItem2 = VSHelpers.GetProjectItem(dtsEnumFile);

                        if (dtsItem2 != null)
                        {
                            dtsItem2.Properties.Item("DependentUpon").Value = sourceItem.Name;
                        }
                    }

                    Telemetry.TrackOperation("FileGenerated");
                }), DispatcherPriority.ApplicationIdle, null);
            }
            else if (sourceItem.ContainingProject.IsKind(ProjectTypes.WEBSITE_PROJECT))
            {
                sourceItem.ContainingProject.ProjectItems.AddFromFile(dtsFile);

                if (isEmptyEnum == false)
                {
                    sourceItem.ContainingProject.ProjectItems.AddFromFile(dtsEnumFile);
                }
            }

            // Also create the definition map data and add it to our project item
            CreateDtsMapFile(sourceItem, definitionMapData);
        }
        public static void ReadOptionOverrides(ProjectItem sourceItem, bool display = true)
        {
            Project proj = sourceItem.ContainingProject;

            string jsonName = "";

            foreach (ProjectItem item in proj.ProjectItems)
            {
                if (item.Name.ToLower() == OVERRIDE_FILE_NAME.ToLower())
                {
                    jsonName = item.FileNames[0];
                    break;
                }
            }

            if (!string.IsNullOrEmpty(jsonName))
            {
                // it has been modified since last read - so read again
                try
                {
                    overrides = JsonConvert.DeserializeObject <OptionsOverride>(File.ReadAllText(jsonName));
                    if (display)
                    {
                        VSHelpers.WriteOnOutputWindow(string.Format("Override file processed: {0}", jsonName));
                    }
                    else
                    {
                        System.Diagnostics.Debug.WriteLine(string.Format("Override file processed: {0}", jsonName));
                    }
                }
                catch (Exception e) when(e is Newtonsoft.Json.JsonReaderException || e is Newtonsoft.Json.JsonSerializationException)
                {
                    overrides = null; // incase the read fails
                    VSHelpers.WriteOnOutputWindow(string.Format("Error in Override file: {0}", jsonName));
                    VSHelpers.WriteOnOutputWindow(e.Message);
                    throw;
                }
            }
            else
            {
                if (display)
                {
                    VSHelpers.WriteOnOutputWindow("Using Global Settings");
                }
                else
                {
                    System.Diagnostics.Debug.WriteLine("Using Global Settings");
                }
                overrides = null;
            }
        }
Пример #11
0
        private void FileActionOccurred(object sender, TextDocumentFileActionEventArgs e)
        {
            if (e.FileActionType != FileActionTypes.ContentSavedToDisk)
            {
                return;
            }
            _item = VSHelpers.GetProjectItem(e.FilePath);
            Options.ReadOptionOverrides(_item, false);
            string fileName = Utility.GenerateFileName(e.FilePath);

            if (File.Exists(fileName))
            {
                DtsPackage.EnsurePackageLoad();
                CreateDtsFile(_item);
            }
        }
 public static string ConvertToTypeScript(ProjectItem sourceItem)
 {
     try
     {
         Options.ReadOptionOverrides(sourceItem);
         VSHelpers.WriteOnOutputWindow(string.Format("{0} - Started", sourceItem.Name));
         var list = IntellisenseParser.ProcessFile(sourceItem);
         VSHelpers.WriteOnOutputWindow(string.Format("{0} - Completed", sourceItem.Name));
         return(IntellisenseWriter.WriteTypeScript(list));
     }
     catch (Exception ex)
     {
         VSHelpers.WriteOnOutputWindow(string.Format("{0} - Failure", sourceItem.Name));
         Telemetry.TrackException("ParseFailure", ex);
         return(null);
     }
 }
Пример #13
0
        public void TextViewCreated(IWpfTextView textView)
        {
            if (!_documentService.TryGetTextDocument(textView.TextBuffer, out var doc))
            {
                return;
            }

            _item = VSHelpers.GetProjectItem(doc.FilePath);

            if (_item?.ContainingProject == null ||
                !_item.ContainingProject.IsKind(ProjectTypes.DOTNET_Core, ProjectTypes.ASPNET_5, ProjectTypes.WEBSITE_PROJECT))
            {
                return;
            }

            doc.FileActionOccurred += FileActionOccurred;
        }
Пример #14
0
        private static void WriteTypescriptToFile(string contents, string typescriptFilename, ProjectItem sourceItem)
        {
            if (!string.IsNullOrEmpty(contents))
            {
                VSHelpers.CheckFileOutOfSourceControl(typescriptFilename);
                File.WriteAllText(typescriptFilename, contents);
                VSHelpers.WriteOnOutputWindow($"Written: {typescriptFilename}");
            }
            else
            {
                try
                {
                    File.Delete(typescriptFilename);
                    VSHelpers.WriteOnOutputWindow($"Deleted (no content): {typescriptFilename}");
                }
                catch { }
            }

            if (sourceItem.ContainingProject.IsKind(ProjectTypes.DOTNET_Core, ProjectTypes.ASPNET_5))
            {
                Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() =>
                {
                    var dtsItem = VSHelpers.GetProjectItem(typescriptFilename);

                    if (!string.IsNullOrEmpty(contents))
                    {
                        if (dtsItem != null)
                        {
                            dtsItem.Properties.Item("DependentUpon").Value = sourceItem.Name;
                        }

                        Telemetry.TrackOperation("FileGenerated");
                    }
                    else
                    {
                        dtsItem.Delete();
                        Telemetry.TrackOperation("FileDeleted");
                    }
                }), DispatcherPriority.ApplicationIdle, null);
            }
            else if (sourceItem.ContainingProject.IsKind(ProjectTypes.WEBSITE_PROJECT) && !string.IsNullOrEmpty(contents))
            {
                sourceItem.ContainingProject.ProjectItems.AddFromFile(typescriptFilename);
            }
        }
        protected override byte[] GenerateCode(string inputFileName, string inputFileContent)
        {
            ProjectItem item = Dte.Solution.FindProjectItem(inputFileName);

            OriginalExt = Path.GetExtension(inputFileName);
            if (item != null)
            {
                try
                {
                    Telemetry.TrackOperation("FileGenerated");

                    string output = GenerationService.ConvertToTypeScript(item);

                    if (!string.IsNullOrWhiteSpace(Options.NodeModulePath))
                    {
                        // generate a Node module instead of a d.ts file.
                        string outputFile  = Path.ChangeExtension(inputFileName, ".ts");
                        string projectPath = Path.GetDirectoryName(item.ContainingProject.FileName);
                        outputFile = outputFile.Substring(projectPath.Length + 1); // strip the initial part of the path
                        outputFile = Path.Combine(projectPath, Options.NodeModulePath, outputFile);
                        var di = Directory.CreateDirectory(Path.GetDirectoryName(outputFile));
                        if (di != null && di.Exists)
                        {
                            VSHelpers.CheckFileOutOfSourceControl(outputFile);
                            File.WriteAllText(outputFile, output);

                            output = $"// Node module file generated at {MakeRelativePath(InputFilePath, outputFile)}";
                        }
                    }

                    return(Encoding.UTF8.GetBytes(output));
                }
                catch (Exception ex)
                {
                    VSHelpers.WriteOnOutputWindow(string.Format("{0} - File Generation Failure", inputFileName));
                    VSHelpers.WriteOnOutputWindow(ex.StackTrace);
                    Telemetry.TrackOperation("FileGenerated", Microsoft.VisualStudio.Telemetry.TelemetryResult.Failure);
                    Telemetry.TrackException("FileGenerated", ex);
                }
            }

            return(new byte[0]);
        }
Пример #16
0
        protected override byte[] GenerateCode(string inputFileName, string inputFileContent)
        {
            ProjectItem item = Dte.Solution.FindProjectItem(inputFileName);

            this.originalExt = Path.GetExtension(inputFileName);
            if (item != null)
            {
                try
                {
                    // Get metadata from our project item
                    DefinitionMapData definitionMapData = VSHelpers.GetDefinitionMapData(item);

                    string dts     = GenerationService.ConvertToTypeScriptWithoutEnums(item, ref definitionMapData, out bool isEmpty);
                    string dtsEnum = GenerationService.ConvertToTypeScriptEnumsOnly(item, ref definitionMapData, out bool isEmptyEnum);
                    Telemetry.TrackOperation("FileGenerated");

                    if (isEmpty == false)
                    {
                        // Copy our dts file to the specified paths in the definition map data
                        GenerationService.CopyDtsFile(definitionMapData, item, dts, false);
                    }

                    if (isEmptyEnum == false)
                    {
                        GenerationService.CopyDtsFile(definitionMapData, item, dtsEnum, true);
                        GenerationService.CreateEnumFile(item, dtsEnum);
                    }

                    // And in the last step write the map file which contains some metadata
                    GenerationService.CreateDtsMapFile(item, definitionMapData);

                    return(Encoding.UTF8.GetBytes(dts));
                }
                catch (Exception ex)
                {
                    Telemetry.TrackOperation("FileGenerated", Microsoft.VisualStudio.Telemetry.TelemetryResult.Failure);
                    Telemetry.TrackException("FileGenerated", ex);
                }
            }

            return(new byte[0]);
        }
Пример #17
0
        private void Execute(object sender, EventArgs e)
        {
            if (_item == null)
            {
                return;
            }
            Options.ReadOptionOverrides(_item, false);
            // .NET Core and Website projects
            if (_item.ContainingProject.IsKind(ProjectTypes.DOTNET_Core, ProjectTypes.ASPNET_5, ProjectTypes.WEBSITE_PROJECT))
            {
                string dtsFile = GenerationService.GenerateFileName(_item.FileNames[1]);
                bool   synOn   = File.Exists(dtsFile);

                if (synOn)
                {
                    var dtsItem = VSHelpers.GetProjectItem(dtsFile);
                    dtsItem?.Delete();
                    File.Delete(dtsFile);
                }
                else
                {
                    GenerationService.CreateDtsFile(_item);
                }
            }
            // Legacy .NET projects
            else
            {
                bool synOn = _item.Properties.Item("CustomTool").Value.ToString() == DtsGenerator.Name;

                if (synOn)
                {
                    _item.Properties.Item("CustomTool").Value = "";
                    Telemetry.TrackUserTask("EnableGeneration");
                }
                else
                {
                    _item.Properties.Item("CustomTool").Value = DtsGenerator.Name;
                    Telemetry.TrackUserTask("DisabledGeneration");
                }
            }
        }
        public static void CreateEnumFile(ProjectItem sourceItem, string content)
        {
            string sourceFile = sourceItem.FileNames[1];
            string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(sourceFile);

            while (fileNameWithoutExtension.Contains("."))
            {
                fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileNameWithoutExtension);
            }

            string dtsFile = Path.Combine(Path.GetDirectoryName(sourceFile), fileNameWithoutExtension += "Enum.ts");

            VSHelpers.CheckFileOutOfSourceControl(dtsFile);
            File.WriteAllText(dtsFile, content);

            if (sourceItem.ContainingProject.IsKind(ProjectTypes.DOTNET_Core, ProjectTypes.ASPNET_5))
            {
                Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() =>
                {
                    var dtsItem = VSHelpers.GetProjectItem(dtsFile);

                    if (dtsItem != null)
                    {
                        dtsItem.Properties.Item("DependentUpon").Value = sourceItem.Name;
                    }

                    Telemetry.TrackOperation("FileGenerated");
                }), DispatcherPriority.ApplicationIdle, null);
            }
            else if (sourceItem.ContainingProject.IsKind(ProjectTypes.WEBSITE_PROJECT))
            {
                sourceItem.ContainingProject.ProjectItems.AddFromFile(dtsFile);
            }
            else
            {
                sourceItem.ProjectItems.AddFromFile(dtsFile);
            }
        }
Пример #19
0
        public static string WriteTypeScriptWithoutEnums(IEnumerable <IntellisenseObject> objects, ProjectItem sourceItem, out bool isEmpty)
        {
            isEmpty = true;

            var sb = new StringBuilder();

            foreach (var ns in objects.GroupBy(o => o.Namespace))
            {
                List <string> references = GetReferences(objects, sourceItem);

                if (references.Count > 0)
                {
                    foreach (string referencePath in references.OrderBy(p => Path.GetFileName(p)))
                    {
                        string path = Path.GetFileName(referencePath);

                        ProjectItem definitionMapProjectItem = sourceItem.DTE.Solution.FindProjectItem(referencePath);

                        if (definitionMapProjectItem != null)
                        {
                            DefinitionMapData definitionMapData = VSHelpers.GetDefinitionMapData(definitionMapProjectItem.Collection.Parent as ProjectItem);

                            if (definitionMapData != null)
                            {
                                if (string.IsNullOrWhiteSpace(definitionMapData.CustomName) == false)
                                {
                                    path = GenerationService.GetCopyDtsFileName(definitionMapData, definitionMapProjectItem, false);
                                }
                            }
                        }

                        sb.AppendFormat("/// <reference path=\"{0}\" />\r\n", path);
                    }

                    sb.AppendLine();
                }

                if (!Options.GlobalScope)
                {
                    sb.AppendFormat("declare module {0} {{\r\n", ns.Key);
                }

                foreach (IntellisenseObject io in ns)
                {
                    if (io.IsEnum)
                    {
                        continue;
                    }

                    isEmpty = false;

                    if (!string.IsNullOrEmpty(io.Summary))
                    {
                        sb.AppendLine("\t/** " + _whitespaceTrimmer.Replace(io.Summary, "") + " */");
                    }

                    string type = Options.ClassInsteadOfInterface ? "\tclass " : "\tinterface ";
                    sb.Append(type).Append(Utility.CamelCaseClassName(io.Name)).Append(" ");

                    if (!string.IsNullOrEmpty(io.BaseName))
                    {
                        sb.Append("extends ");

                        if (Options.GlobalScope == false)
                        {
                            sb.Append(ns.Key).Append(".");
                        }

                        if (!string.IsNullOrEmpty(io.BaseNamespace) && io.BaseNamespace != io.Namespace)
                        {
                            sb.Append(io.BaseNamespace).Append(".");
                        }

                        sb.Append(Utility.CamelCaseClassName(io.BaseName)).Append(" ");
                    }

                    WriteTSInterfaceDefinition(sb, "\t", io.Properties);
                    sb.AppendLine();
                }

                if (!Options.GlobalScope)
                {
                    sb.AppendLine("}");
                }
            }

            return(sb.ToString());
        }
Пример #20
0
        public static string WriteTypeScriptEnumsOnly(IEnumerable <IntellisenseObject> objects, ProjectItem sourceItem, out bool isEmpty)
        {
            isEmpty = true;

            var sb = new StringBuilder();

            foreach (var ns in objects.GroupBy(o => o.Namespace))
            {
                List <string> references = GetReferences(objects, sourceItem);

                if (references.Count > 0)
                {
                    foreach (string referencePath in references.OrderBy(p => Path.GetFileName(p)))
                    {
                        string path = Path.GetFileName(referencePath);

                        ProjectItem definitionMapProjectItem = sourceItem.DTE.Solution.FindProjectItem(referencePath);

                        if (definitionMapProjectItem != null)
                        {
                            DefinitionMapData definitionMapData = VSHelpers.GetDefinitionMapData(definitionMapProjectItem.Collection.Parent as ProjectItem);

                            if (definitionMapData != null)
                            {
                                if (string.IsNullOrWhiteSpace(definitionMapData.CustomName) == false)
                                {
                                    path = GenerationService.GetCopyDtsFileName(definitionMapData, definitionMapProjectItem, true);
                                }
                            }
                        }

                        sb.AppendFormat("/// <reference path=\"{0}\" />\r\n", path);
                    }

                    sb.AppendLine();
                }

                if (!Options.GlobalScope)
                {
                    sb.AppendFormat("declare module {0} {{\r\n", ns.Key);
                }

                foreach (IntellisenseObject io in ns)
                {
                    if (io.IsEnum == false)
                    {
                        continue;
                    }

                    isEmpty = false;

                    if (!string.IsNullOrEmpty(io.Summary))
                    {
                        sb.AppendLine("\t/** " + _whitespaceTrimmer.Replace(io.Summary, "") + " */");
                    }

                    sb.AppendLine("\tenum " + Utility.CamelCaseClassName(io.Name) + " {");

                    foreach (var p in io.Properties)
                    {
                        WriteTypeScriptComment(p, sb);

                        if (p.InitExpression != null)
                        {
                            sb.AppendLine("\t\t" + Utility.CamelCaseEnumValue(p.Name) + " = " + CleanEnumInitValue(p.InitExpression) + ",");
                        }
                        else
                        {
                            sb.AppendLine("\t\t" + Utility.CamelCaseEnumValue(p.Name) + ",");
                        }
                    }

                    sb.AppendLine("\t}");
                }

                if (!Options.GlobalScope)
                {
                    sb.AppendLine("}");
                }
            }

            return(sb.ToString());
        }
        private static IntellisenseType GetType(CodeClass rootElement, CodeTypeRef codeTypeRef, HashSet <string> traversedTypes, HashSet <string> references)
        {
            var isArray      = codeTypeRef.TypeKind == vsCMTypeRef.vsCMTypeRefArray;
            var isCollection = codeTypeRef.AsString.StartsWith("System.Collections", StringComparison.Ordinal);
            var isDictionary = false;

            var effectiveTypeRef = codeTypeRef;

            if (isArray && codeTypeRef.ElementType != null)
            {
                effectiveTypeRef = effectiveTypeRef.ElementType;
            }
            else if (isCollection)
            {
                effectiveTypeRef = TryToGuessGenericArgument(rootElement, effectiveTypeRef);
            }

            if (isCollection)
            {
                isDictionary = codeTypeRef.AsString.StartsWith("System.Collections.Generic.Dictionary", StringComparison.Ordinal) ||
                               codeTypeRef.AsString.StartsWith("System.Collections.Generic.IDictionary", StringComparison.Ordinal);
            }

            string typeName = effectiveTypeRef.AsFullName;

            try
            {
                //VSHelpers.WriteOnBuildDebugWindow($"%{(effectiveTypeRef.CodeType as CodeInterface2) != null}%");
                var codeInterface = effectiveTypeRef.CodeType as CodeInterface2;
                var codeClass     = effectiveTypeRef.CodeType as CodeClass2;
                var codeEnum      = effectiveTypeRef.CodeType as CodeEnum;
                var isPrimitive   = IsPrimitive(effectiveTypeRef);
                //VSHelpers.WriteOnBuildDebugWindow($"###{effectiveTypeRef.CodeType.GetType().FullName}");

                var result = new IntellisenseType
                {
                    IsArray      = !isDictionary && (isArray || isCollection),
                    IsDictionary = isDictionary,
                    CodeName     = effectiveTypeRef.AsString
                };

                //VSHelpers.WriteOnBuildDebugWindow($"#{result.CodeName}#{result.TypeScriptName}#{effectiveTypeRef.AsString}#{effectiveTypeRef.AsFullName}#{effectiveTypeRef.CodeType}");
                //VSHelpers.WriteOnBuildDebugWindow($"##{effectiveTypeRef.TypeKind}##{vsCMTypeRef.vsCMTypeRefCodeType}##{effectiveTypeRef.CodeType.InfoLocation}##{vsCMInfoLocation.vsCMInfoLocationProject}");

                result.ClientSideReferenceName = null;
                if (effectiveTypeRef.TypeKind == vsCMTypeRef.vsCMTypeRefCodeType)
                {
                    var hasIntellisense = Options.IgnoreIntellisense;
                    if (effectiveTypeRef.CodeType.InfoLocation == vsCMInfoLocation.vsCMInfoLocationProject)
                    {
                        if (codeClass != null)
                        {
                            hasIntellisense = HasIntellisense(codeClass.ProjectItem, references);
                        }
                        if (codeEnum != null)
                        {
                            hasIntellisense = HasIntellisense(codeEnum.ProjectItem, references);
                        }
                    }

                    //VSHelpers.WriteOnBuildDebugWindow($"@{codeClass != null}@{codeEnum != null}@{hasIntellisense}@{Options.DeclareModule}");
                    result.ClientSideReferenceName = (codeClass != null && hasIntellisense ? (Options.DeclareModule ? GetNamespace(codeClass) + "." : "") + Utility.CamelCaseClassName(GetClassName(codeClass)) : null) ??
                                                     (codeEnum != null && hasIntellisense ? (Options.DeclareModule ? GetNamespace(codeEnum) + "." : "") + Utility.CamelCaseClassName(GetEnumName(codeEnum)) : null) ??
                                                     (codeInterface != null && hasIntellisense ? (Options.DeclareModule ? GetNamespace(codeInterface) + "." : "") + Utility.CamelCaseClassName(GetInterfaceName(codeInterface)) : null);
                }

                if (!isPrimitive && (codeClass != null || codeEnum != null) && !traversedTypes.Contains(effectiveTypeRef.CodeType.FullName) && !isCollection)
                {
                    traversedTypes.Add(effectiveTypeRef.CodeType.FullName);
                    result.Shape = GetProperties(effectiveTypeRef.CodeType.Members, traversedTypes, references).ToList();
                    traversedTypes.Remove(effectiveTypeRef.CodeType.FullName);
                }

                return(result);
            }
            catch (InvalidCastException)
            {
                VSHelpers.WriteOnOutputWindow(string.Format("ERROR - Cannot find definition for {0}", typeName));
                throw new ArgumentException(string.Format("Cannot find definition of {0}", typeName));
            }
        }
Пример #22
0
        /// <summary>
        /// Generates TypeScript file for given C# class/enum (IntellisenseObject).
        /// </summary>
        /// <param name="objects">IntellisenseObject of class/enum</param>
        /// <param name="sourceItemPath">Path to C# source file</param>
        /// <returns>TypeScript file content as string</returns>
        public static string WriteTypeScript(IList <IntellisenseObject> objects, string sourceItemPath)
        {
            var sb = new StringBuilder();

            sb.AppendLine("// ------------------------------------------------------------------------------");
            sb.AppendLine("// <auto-generated>");
            sb.AppendFormat("//     This file was generated by TypeScript Definition Generator v{0}\r\n", Vsix.Version);
            sb.AppendLine("// </auto-generated>");
            sb.AppendLine("// ------------------------------------------------------------------------------");

            string export       = !Options.DeclareModule ? "export " : string.Empty;
            string prefixModule = Options.DeclareModule ? "\t" : string.Empty;

            var sbBody = new StringBuilder();

            var neededImports = new List <string>();

            foreach (var ns in objects.GroupBy(o => o.Namespace))
            {
                if (Options.DeclareModule)
                {
                    sbBody.AppendFormat("declare module {0} {{\r\n", ns.Key);
                }

                foreach (IntellisenseObject io in ns)
                {
                    if (!string.IsNullOrEmpty(io.Summary))
                    {
                        sbBody.Append(prefixModule).AppendLine("/** " + _whitespaceTrimmer.Replace(io.Summary, "") + " */");
                    }

                    if (io.IsEnum)
                    {
                        string type = "enum ";
                        sbBody.Append(prefixModule).Append(export).Append(type).Append(Utility.CamelCaseClassName(io.Name)).Append(" ");

                        sbBody.AppendLine("{");
                        WriteTSEnumDefinition(sbBody, prefixModule + "\t", io.Properties);
                        sbBody.Append(prefixModule).AppendLine("}");
                    }
                    else
                    {
                        string type = Options.ClassInsteadOfInterface ? "class " : "interface ";
                        sbBody.Append(prefixModule).Append(export).Append(type).Append(Utility.CamelCaseClassName(io.Name)).Append(" ");

                        if (!string.IsNullOrEmpty(io.BaseName))
                        {
                            sbBody.Append("extends ");

                            if (!string.IsNullOrEmpty(io.BaseNamespace) && io.BaseNamespace != io.Namespace)
                            {
                                sbBody.Append(io.BaseNamespace).Append(".");
                            }

                            sbBody.Append(Utility.CamelCaseClassName(io.BaseName)).Append(" ");
                        }

                        sbBody.AppendLine("{");
                        WriteTSInterfaceDefinition(sbBody, prefixModule + "\t", io.Properties);
                        sbBody.Append(prefixModule).AppendLine("}");
                        // Remember client-side references for which we need imports.
                        // Dictionary are built-in into TS, they need no imports.
                        neededImports.AddRange(io.Properties.Where(p => p.Type.ClientSideReferenceName != null &&
                                                                   !p.Type.IsDictionary).Select(p => p.Type.ClientSideReferenceName));
                    }
                }

                if (Options.DeclareModule)
                {
                    sbBody.AppendLine("}");
                }
            }

            // if interface, import external interfaces and base classes
            if (!Options.DeclareModule)
            {
                var imports = new List <string>();

                var references = objects.SelectMany(o => o.References).Distinct();
                foreach (var reference in references)
                {
                    var referencePathRelative = Utility.GetRelativePath(sourceItemPath, reference);
                    // remove trailing ".ts" which is not expected for TS imports
                    referencePathRelative = referencePathRelative.Substring(0, referencePathRelative.Length - 3);
                    // make sure path contains forward slashes which are expected by TS
                    referencePathRelative = referencePathRelative.Replace(Path.DirectorySeparatorChar, '/');
                    var referenceName = Utility.RemoveDefaultExtension(Path.GetFileName(reference));

                    // skipped indirect references
                    if (!neededImports.Contains(referenceName))
                    {
                        continue;
                    }

                    sb.AppendLine($"import {{ {referenceName} }} from \"{referencePathRelative}\";");
                    imports.Add(referenceName);
                }

                // also import base classes if not yet imported
                var baseClasses = objects.Select(o => o.BaseName).Where(b => b != null && !imports.Contains(b)).Distinct();
                foreach (var b in baseClasses)
                {
                    var expectedBaseClassPath = Path.Combine(Path.GetDirectoryName(sourceItemPath), b + ".cs");
                    if (!File.Exists(expectedBaseClassPath))
                    {
                        throw new ExceptionForUser($"Could not find base class for {b}. Expected path: {expectedBaseClassPath}");
                    }

                    sb.AppendLine($"import {{ {b} }} from \"./{b}.generated\";");
                    imports.Add(b);
                }

                var notImportedNeededImports = neededImports.Except(imports).ToList();
                if (notImportedNeededImports.Any())
                {
                    var exceptionForDeveloper =
                        $"Sorry, needed imports missing: {string.Join(", ", notImportedNeededImports)}. " +
                        $"Make sure file names match contained class/enum name.";
                    sb.AppendLine($"// {exceptionForDeveloper}");
                    VSHelpers.WriteOnOutputWindow(exceptionForDeveloper);
                    //throw new ExceptionForUser(exceptionForDeveloper);
                }
            }

            sb.Append(sbBody);

            if (Options.EOLType == EOLType.LF)
            {
                sb.Replace("\r\n", "\n");
            }

            if (!Options.IndentTab)
            {
                sb.Replace("\t", new string(' ', Options.IndentTabSize));
            }

            return(sb.ToString());
        }
        /// <summary>
        /// Generates TypeScript file for given C# class/enum (IntellisenseObject).
        /// </summary>
        /// <param name="objects">IntellisenseObject of class/enum</param>
        /// <param name="sourceItemPath">Path to C# source file</param>
        /// <returns>TypeScript file content as string</returns>
        public static string WriteTypeScript(IList <IntellisenseObject> objects, string sourceItemPath)
        {
            var sb = new StringBuilder();

            if (Options.AddAmdModuleName)
            {
                var moduleName = Path.GetFileNameWithoutExtension(sourceItemPath)
                                 + Path.GetFileNameWithoutExtension(Utility.GetDefaultExtension(sourceItemPath));
                sb.AppendLine($"/// <amd-module name='{moduleName}'/>");
            }

            sb.AppendLine("// ------------------------------------------------------------------------------");
            sb.AppendLine("// <auto-generated>");
            sb.AppendFormat("//     This file was generated by TypeScript Definition Generator v{0}\r\n", Vsix.Version);
            sb.AppendLine("// </auto-generated>");
            sb.AppendLine("// ------------------------------------------------------------------------------");

            string export       = !Options.DeclareModule ? "export " : string.Empty;
            string prefixModule = Options.DeclareModule ? "\t" : string.Empty;

            var sbBody = new StringBuilder();

            var neededImports = new List <string>();
            var imports       = new List <string>();
            var exports       = new List <string>();

            foreach (var ns in objects.GroupBy(o => o.Namespace))
            {
                if (Options.DeclareModule)
                {
                    sbBody.AppendFormat("declare module {0} {{\r\n", ns.Key);
                }

                foreach (IntellisenseObject io in ns)
                {
                    WriteTypeScriptComment(io.Summary, sbBody, prefixModule);

                    if (io.IsEnum)
                    {
                        string type = "const enum ";
                        sbBody.Append(prefixModule).Append(export).Append(type).Append(Utility.CamelCaseClassName(io.Name)).Append(" ");
                        if (!Options.DeclareModule)
                        {
                            exports.Add(Utility.CamelCaseClassName(io.Name));
                        }

                        sbBody.AppendLine("{");
                        WriteTSEnumDefinition(sbBody, prefixModule + "\t", io.Properties);
                        sbBody.Append(prefixModule).AppendLine("}");
                    }
                    else
                    {
                        string type = Options.ClassInsteadOfInterface ? "class " : "interface ";
                        sbBody.Append(prefixModule).Append(export).Append(type).Append(Utility.CamelCaseClassName(io.Name)).Append(" ");
                        if (!Options.DeclareModule)
                        {
                            exports.Add(Utility.CamelCaseClassName(io.Name));
                        }

                        string[] summaryLines = io.Summary?.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
                        string   optionsLine  = summaryLines?.SingleOrDefault(l => l.StartsWith("TypeScriptDefinitionGenerator:"));
                        var      ignoreBase   = optionsLine != null && optionsLine.Contains("IgnoreBaseType");

                        if (!string.IsNullOrEmpty(io.BaseName) && !ignoreBase)
                        {
                            var extendsContent = string.Empty;
                            sbBody.Append("#{ExtendsPlaceholder_" + io.BaseName + "}");
                            if (!string.IsNullOrEmpty(io.BaseNamespace) && io.BaseNamespace != io.Namespace)
                            {
                                extendsContent = $"extends {io.BaseNamespace}.{Utility.CamelCaseClassName(io.BaseName)} ";
                            }
                            else
                            {
                                extendsContent = $"extends {Utility.CamelCaseClassName(io.BaseName)} ";
                            }

                            if (!ExtendsPlaceholders.ContainsKey(io.BaseName))
                            {
                                ExtendsPlaceholders.Add(io.BaseName, extendsContent);
                            }
                        }

                        sbBody.AppendLine("{");
                        WriteTSInterfaceDefinition(sbBody, prefixModule + "\t", io.Properties);
                        sbBody.Append(prefixModule).AppendLine("}");
                        // Remember client-side references for which we need imports.
                        // Dictionary are built-in into TS, they need no imports.
                        neededImports.AddRange(io.Properties.Where(p => p.Type.ClientSideReferenceName != null &&
                                                                   !p.Type.IsDictionary).Select(p => p.Type.ClientSideReferenceName));
                        // Remember that this class was already included (imported)
                        imports.Add(Utility.CamelCaseClassName(io.Name));
                    }
                }

                if (Options.DeclareModule)
                {
                    sbBody.AppendLine("}");
                }
            }

            neededImports.RemoveAll(n => imports.Contains(n));

            // if interface, import external interfaces and base classes
            if (!Options.DeclareModule)
            {
                var references = objects.SelectMany(o => o.References).Distinct();
                foreach (var reference in references)
                {
                    var referencePathRelative = Utility.GetRelativePath(sourceItemPath, reference);
                    // remove trailing ".ts" which is not expected for TS imports
                    referencePathRelative = referencePathRelative.Substring(0, referencePathRelative.Length - 3);
                    // make sure path contains forward slashes which are expected by TS
                    referencePathRelative = referencePathRelative.Replace(Path.DirectorySeparatorChar, '/');
                    var referenceName = Utility.RemoveDefaultExtension(Path.GetFileName(reference));

                    // skipped indirect references
                    if (!neededImports.Contains(referenceName))
                    {
                        continue;
                    }

                    sb.AppendLine($"import {{ {referenceName} }} from \"{referencePathRelative}\";");
                    imports.Add(referenceName);
                }

                // also import base classes if not yet imported
                var baseClasses = objects.Select(o => o.BaseName).Where(b => b != null && !imports.Contains(b)).Distinct();
                foreach (var b in baseClasses)
                {
                    var expectedBaseClassPath = Path.Combine(Path.GetDirectoryName(sourceItemPath), b + ".cs");
                    if (!File.Exists(expectedBaseClassPath))
                    {
                        var warningMessage =
                            $"Sorry, ignoring base class '{b}' because expected source file does not exist: {expectedBaseClassPath} ";
                        sb.AppendLine($"// {warningMessage}");
                        VSHelpers.WriteOnOutputWindow(warningMessage);
                        // remove placeholder from sbBody to prevent "extends " to be inserted later
                        sbBody.Replace("#{ExtendsPlaceholder_" + b + "}", string.Empty);
                    }
                    else
                    {
                        sb.AppendLine($"import {{ {b} }} from \"./{b}.generated\";");
                        imports.Add(b);
                    }
                }

                var notImportedNeededImports = neededImports.Except(imports).Except(exports).ToList();
                if (notImportedNeededImports.Any())
                {
                    var warningMessage =
                        $"Sorry, needed imports missing: {string.Join(", ", notImportedNeededImports)}. " +
                        $"Make sure file names match contained class/enum name.";
                    sb.AppendLine($"// {warningMessage}");
                    VSHelpers.WriteOnOutputWindow(warningMessage);
                }
            }

            foreach (var placeholder in ExtendsPlaceholders)
            {
                sbBody.Replace("#{ExtendsPlaceholder_" + placeholder.Key + "}", placeholder.Value);
            }

            sb.Append(sbBody);

            if (Options.EOLType == EOLType.LF)
            {
                sb.Replace("\r\n", "\n");
            }

            if (!Options.IndentTab)
            {
                sb.Replace("\t", new string(' ', Options.IndentTabSize));
            }

            return(sb.ToString());
        }
Пример #24
0
        private static IntellisenseType GetType(ProjectItem projectItem, DefinitionMapData definitionMapData, CodeClass rootElement, CodeTypeRef codeTypeRef, HashSet <string> traversedTypes, HashSet <string> references)
        {
            var isArray      = codeTypeRef.TypeKind == vsCMTypeRef.vsCMTypeRefArray;
            var isCollection = codeTypeRef.AsString.StartsWith("System.Collections", StringComparison.Ordinal);
            var isNullable   = codeTypeRef.AsFullName.StartsWith("System.Nullable", StringComparison.Ordinal);
            var isDictionary = false;

            var effectiveTypeRef = codeTypeRef;

            if (isArray && codeTypeRef.ElementType != null)
            {
                effectiveTypeRef = effectiveTypeRef.ElementType;
            }
            else if (isCollection || isNullable)
            {
                effectiveTypeRef = TryToGuessGenericArgument(rootElement, effectiveTypeRef);
            }

            if (isCollection)
            {
                isDictionary = codeTypeRef.AsString.StartsWith("System.Collections.Generic.Dictionary", StringComparison.Ordinal);
            }

            string typeName = effectiveTypeRef.AsFullName;

            try
            {
                var codeClass   = effectiveTypeRef.CodeType as CodeClass2;
                var codeEnum    = effectiveTypeRef.CodeType as CodeEnum;
                var isPrimitive = IsPrimitive(effectiveTypeRef);

                // Some definitions may be defined inside of another project
                if (Options.AssumeExternalType == false && (codeClass != null || codeEnum != null) && effectiveTypeRef.TypeKind == vsCMTypeRef.vsCMTypeRefCodeType && effectiveTypeRef.CodeType.InfoLocation == vsCMInfoLocation.vsCMInfoLocationExternal)
                {
                    // Try retrieving the external codeclass by walking all references the current project has
                    if (TryGetExternalType(projectItem, definitionMapData, codeClass != null ? codeClass.FullName : codeEnum.FullName, out CodeClass2 externalCodeClass, out CodeEnum externalCodeEnum))
                    {
                        // If successful use the new type
                        codeClass = externalCodeClass;
                        codeEnum  = externalCodeEnum;
                    }
                }

                var result = new IntellisenseType
                {
                    IsArray      = !isDictionary && (isArray || isCollection),
                    IsDictionary = isDictionary,
                    IsOptional   = isNullable,
                    CodeName     = effectiveTypeRef.AsString
                };
                if (effectiveTypeRef.TypeKind == vsCMTypeRef.vsCMTypeRefCodeType &&
                    (effectiveTypeRef.CodeType.InfoLocation == vsCMInfoLocation.vsCMInfoLocationProject ||
                     (Options.AssumeExternalType == false && effectiveTypeRef.CodeType.InfoLocation == vsCMInfoLocation.vsCMInfoLocationExternal)))
                {
                    try
                    {
                        result.ClientSideReferenceName = (codeClass != null && HasIntellisense(codeClass.ProjectItem, references) ? (GetNamespace(codeClass) + "." + Utility.CamelCaseClassName(GetClassName(codeClass))) : null) ??
                                                         (codeEnum != null && HasIntellisense(codeEnum.ProjectItem, references) ? (GetNamespace(codeEnum) + "." + Utility.CamelCaseClassName(codeEnum.Name)) : null);
                    }
                    catch (Exception) { }
                }
                else if (Options.AssumeExternalType && effectiveTypeRef.TypeKind == vsCMTypeRef.vsCMTypeRefCodeType && effectiveTypeRef.CodeType.InfoLocation == vsCMInfoLocation.vsCMInfoLocationExternal)
                {
                    try
                    {
                        result.ClientSideReferenceName = (codeClass != null ? (GetNamespace(codeClass) + "." + Utility.CamelCaseClassName(GetClassName(codeClass))) : null) ??
                                                         (codeEnum != null ? (GetNamespace(codeEnum) + "." + Utility.CamelCaseClassName(codeEnum.Name)) : null);
                    }
                    catch (Exception) { }
                }
                else
                {
                    result.ClientSideReferenceName = null;
                }

                if (!isPrimitive && codeClass != null && !traversedTypes.Contains(effectiveTypeRef.CodeType.FullName) && !isCollection)
                {
                    traversedTypes.Add(effectiveTypeRef.CodeType.FullName);
                    result.Shape = GetProperties(projectItem, definitionMapData, effectiveTypeRef.CodeType.Members, traversedTypes, references).ToList();
                    traversedTypes.Remove(effectiveTypeRef.CodeType.FullName);
                }

                return(result);
            }
            catch (InvalidCastException)
            {
                VSHelpers.WriteOnOutputWindow(string.Format("ERROR - Cannot find definition for {0}", typeName));
                throw new ArgumentException(string.Format("Cannot find definition of {0}", typeName));
            }
        }