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 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); } }
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}"); } } }
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; } }
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); } }
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]); }
/// <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()); }
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)); } }
/// <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()); }
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)); } }