public virtual void WriteTypescript(TsOutputer outputter)
 {
     foreach (var child in Children.Values.OrderBy(x => x.DisplayText))
     {
         child.WriteTypescript(outputter);
     }
 }
 public virtual void GetTypescriptComment(TsOutputer outputter)
 {
     if (string.IsNullOrEmpty(Summary))
     {
         return;
     }
     outputter.AppendLine("/** " + Summary.Trim() + " */");
 }
 public override void WriteTypescript(TsOutputer outputter)
 {
     base.GetTypescriptComment(outputter);
     outputter.AppendLine("declare namespace " + DisplayText + " {");
     outputter.IncreaseIndent();
     base.WriteTypescript(outputter);
     outputter.DecreaseIndent();
     outputter.AppendLine("}");
     outputter.OutputBuilder.AppendLine();
 }
        public override void WriteTypescript(TsOutputer outputter)
        {
            if (Children.Count > 0 || IsReferenced)
            {
                base.GetTypescriptComment(outputter);

                outputter.AppendLine("interface " + DisplayText + GetInterfaceExtensionString() + " {");
                outputter.IncreaseIndent();
                base.WriteTypescript(outputter);
                outputter.DecreaseIndent();
                outputter.AppendLine("}");
                outputter.OutputBuilder.AppendLine();
            }
        }
示例#5
0
        public override void WriteTypescript(TsOutputer outputter)
        {
            base.GetTypescriptComment(outputter);
            // TODO: const?
            outputter.AppendLine("enum " + DisplayText + " {");
            outputter.IncreaseIndent();
            base.WriteTypescript(outputter);
            // remove last comma
            int index = outputter.OutputBuilder.Length - 1;

            while (char.IsWhiteSpace(outputter.OutputBuilder[index]))
            {
                index--;
            }
            if (outputter.OutputBuilder[index] == ',')
            {
                outputter.OutputBuilder.Remove(index, 1);
            }

            outputter.DecreaseIndent();
            outputter.AppendLine("}");
        }
 public override void WriteTypescript(TsOutputer outputter)
 {
     base.GetTypescriptComment(outputter);
     outputter.AppendLine(this.DisplayText + GetValueString() + ",");
 }
示例#7
0
        public static async Task <IEnumerable <TsCodeGenerationResult> > GenerateCode(Solution solution, IEnumerable <string> projects, ITypescriptGeneratorTargetProvider tgtProvider, bool wholeSolution)
        {
            _solution = solution;

            if (projects != null)
            {
                foreach (var projectFile in projects.Where(x => x.EndsWith(".csproj", StringComparison.OrdinalIgnoreCase)))
                {
                    _projects.Enqueue(projectFile);
                }
            }

            if (_projects.Count == 0)
            {
                PopulateProjects();
            }

            // Each project's contents are stored as a dictionary of namespaces (since they will be stored that way in file form for TS generation).
            Dictionary <string, CSharpNamespace> namespaces             = new Dictionary <string, CSharpNamespace>();
            Dictionary <string, CSharpReference> referencesPendingParse = new Dictionary <string, CSharpReference>();
            HashSet <string> referenced     = new HashSet <string>();
            HashSet <string> parsedProjects = new HashSet <string>(StringComparer.OrdinalIgnoreCase);

            // Phase 1: go through all projects to parse their contents
            while (_projects.Count > 0)
            {
                var projName = _projects.Dequeue();
                if (parsedProjects.Contains(projName))
                {
                    continue;
                }

                Project project = _solution.Projects.FirstOrDefault(x => x.FilePath != null && x.FilePath.Equals(projName, StringComparison.OrdinalIgnoreCase));
                if (project != null)
                {
                    var compUnit = project.GetCompilationAsync().Result;
                    var context  = new TsContext();
                    var output   = new TsOutputer();

                    foreach (var st in compUnit.SyntaxTrees)
                    {
                        var semanticModel = compUnit.GetSemanticModel(st);
                        var root          = st.GetRoot();
                        var tsw           = new TSWalker(st, output, context, semanticModel);
                        tsw.Visit(root);

                        // Collect the namespaces from this file and store them for the project
                        foreach (var nsKvp in tsw.CSFile.Elements)
                        {
                            CSharpNamespace existingNsObj;
                            if (namespaces.TryGetValue(nsKvp.Key, out existingNsObj))
                            {
                                existingNsObj.Merge(nsKvp.Value);
                            }
                            else
                            {
                                nsKvp.Value.ProjectPath = project.FilePath;
                                namespaces.Add(nsKvp.Key, nsKvp.Value);
                            }
                        }

                        // get references needed by the file
                        foreach (var refKvp in tsw.CSFile.GetReferences())
                        {
                            referenced.Add(refKvp.Key);
                            // TODO: get the namespace and the name of the reference
                            string ns, name;
                            Extensions.GetNamespaceAndName(refKvp.Key, out ns, out name);

                            // try to get existing namespace
                            CSharpNamespace existingNs;
                            if (namespaces.TryGetValue(ns, out existingNs))
                            {
                                // look for the reference in the namespace's children
                                ICSharpFileElement fileEle;
                                if (existingNs.Children.TryGetValue(name, out fileEle))
                                {
                                    var clsObj = fileEle as CSharpClass;
                                    if (clsObj != null)
                                    {
                                        clsObj.IsReferenced = true;
                                    }
                                    // move on.
                                    continue;
                                }
                            }

                            // If we're at this point, either we haven't parsed anything to produce the namespace,
                            // or the namespace doesn't contain the reference yet.
                            // Either way, we need to store the reference off for future resolution
                            if (!referencesPendingParse.ContainsKey(refKvp.Key))
                            {
                                referencesPendingParse.Add(refKvp.Key, refKvp.Value);
                            }
                        }
                    }

                    // check the references pending parse and see if any have been parsed since the project parsing finished.
                    var pendingParseKeys = referencesPendingParse.Keys.ToList();
                    foreach (var pendingKey in pendingParseKeys)
                    {
                        string ns, name;
                        Extensions.GetNamespaceAndName(pendingKey, out ns, out name);

                        // try to get existing namespace
                        CSharpNamespace existingNs;
                        if (namespaces.TryGetValue(ns, out existingNs))
                        {
                            // look for the reference in the namespace's children
                            ICSharpFileElement fileEle;
                            if (existingNs.Children.TryGetValue(name, out fileEle))
                            {
                                var clsObj = fileEle as CSharpClass;
                                if (clsObj != null)
                                {
                                    clsObj.IsReferenced = true;
                                }
                                // remove from pending
                                referencesPendingParse.Remove(pendingKey);
                            }
                        }
                    }

                    parsedProjects.Add(projName);

                    if (referencesPendingParse.Count > 0)
                    {
                        HashSet <string> refProjects = new HashSet <string>(StringComparer.OrdinalIgnoreCase);
                        // Determine the projects that contain these items
                        foreach (var refFile in referencesPendingParse.Values)
                        {
                            foreach (var location in refFile.DeclaringLocations)
                            {
                                string projPath = null;
                                var    temp     = location;
                                do
                                {
                                    var tempDir   = Path.GetDirectoryName(temp);
                                    var dirInfo   = new DirectoryInfo(tempDir);
                                    var projFiles = dirInfo.GetFiles("*.csproj", SearchOption.TopDirectoryOnly);
                                    if (projFiles.Length == 1)
                                    {
                                        projPath = projFiles[0].FullName;
                                    }
                                    else if (projFiles.Length > 1)
                                    {
                                        // TODO: not sure what to do here
                                    }
                                    else
                                    {
                                        temp = tempDir;
                                    }
                                }while (projPath == null);

                                refProjects.Add(projPath);
                            }
                        }

                        foreach (var refProj in refProjects)
                        {
                            _projects.Enqueue(refProj);
                        }
                    }
                }
            }

            // Phase 2:
            // go through all namespaces and mark files that are referenced. This is needed so we can exlude classes that have zero properties that aren't referenced
            foreach (var ns in namespaces)
            {
                // go through all children and mark referenced classes
                foreach (var clsEle in ns.Value.Children.Where(x => x.Value is CSharpClass))
                {
                    var clsNs = string.Format("{0}.{1}", ns.Key, clsEle.Key);
                    if (referenced.Contains(clsNs))
                    {
                        (clsEle.Value as CSharpClass).IsReferenced = true;
                    }
                }
            }

            Dictionary <string, List <string> > projectReferenceFiles = new Dictionary <string, List <string> >(StringComparer.OrdinalIgnoreCase);
            List <TsCodeGenerationResult>       resultFiles           = new List <TsCodeGenerationResult>();

            // Phase 3:
            // Group namespaces by project path, so that namespace files can be written for the appropriate project
            WriteMessage("Generating typings files...");
            foreach (var projectGroup in namespaces.Values.GroupBy(x => x.ProjectPath, StringComparer.OrdinalIgnoreCase))
            {
                List <string> generatedFiles = new List <string>();
                foreach (var ns in projectGroup)
                {
                    if (ns.ShouldWrite)
                    {
                        string filenameToWrite = null;
                        if (tgtProvider != null)
                        {
                            filenameToWrite = tgtProvider.GetTargetFilename(ns.DisplayText, projectGroup.Key);
                        }
                        if (filenameToWrite == null)
                        {
                            filenameToWrite = GetDefaultTargetFilename(ns.DisplayText, projectGroup.Key);
                        }

                        TsOutputer outputter = new TsOutputer();
                        ns.WriteTypescript(outputter);

                        StringBuilder sb     = new StringBuilder();
                        var           nsRefs = ns.GetReferences().Select(x =>
                        {
                            string localNs, localName;
                            Extensions.GetNamespaceAndName(x.Key, out localNs, out localName);
                            return(localNs);
                        }).Where(y => y != ns.DisplayText);
                        HashSet <string> uniqueNsReferences = new HashSet <string>(nsRefs);

                        if (uniqueNsReferences.Count > 0)
                        {
                            foreach (var reference in uniqueNsReferences.OrderBy(x => x))
                            {
                                string          containingProject = null;
                                CSharpNamespace namespaceObj;
                                if (namespaces.TryGetValue(reference, out namespaceObj))
                                {
                                    containingProject = namespaceObj.ProjectPath;
                                }
                                else
                                {
                                    containingProject = projectGroup.Key;
                                }
                                string nsFilename = null;
                                if (tgtProvider != null)
                                {
                                    nsFilename = tgtProvider.GetTargetFilename(reference, containingProject);
                                }
                                if (nsFilename == null)
                                {
                                    nsFilename = GetDefaultTargetFilename(reference, containingProject);
                                }
                                sb.AppendFormat("/// <reference path=\"{0}\" />\r\n", FileHelpers.RelativePath(filenameToWrite, nsFilename));
                            }

                            sb.AppendLine();
                        }

                        sb.Append(outputter.GetContent());
                        if (sb.Length > 0)
                        {
                            var fileResult = await FileHelpers.WriteAllTextRetry(filenameToWrite, sb.ToString(), tgtProvider.EnsureFileIsWritable);

                            if (fileResult.ErrorMessage != null)
                            {
                                WriteMessage(fileResult.ErrorMessage);
                            }
                            resultFiles.Add(fileResult);
                            generatedFiles.Add(filenameToWrite);
                        }
                    }
                }

                if (generatedFiles.Count > 0)
                {
                    string referencesFilePath = null;
                    if (tgtProvider != null)
                    {
                        referencesFilePath = tgtProvider.GetDefaultTargetReferencesFilename(projectGroup.Key);
                    }
                    if (referencesFilePath == null)
                    {
                        referencesFilePath = GetDefaultTargetReferencesFilename(projectGroup.Key);
                    }

                    List <string> existingList;
                    if (projectReferenceFiles.TryGetValue(referencesFilePath, out existingList))
                    {
                        existingList.AddRange(generatedFiles);
                    }
                    else
                    {
                        projectReferenceFiles.Add(referencesFilePath, new List <string>(generatedFiles));
                    }
                }
            }

            WriteMessage("Generating reference files...");
            foreach (var refFile in projectReferenceFiles)
            {
                StringBuilder sb = new StringBuilder();
                if (!wholeSolution && File.Exists(refFile.Key))
                {
                    sb.Append(File.ReadAllText(refFile.Key));
                }
                bool             write         = false;
                Regex            r             = new Regex(@"/// <reference path=""(.*)"" />", RegexOptions.Multiline);
                HashSet <string> existingPaths = new HashSet <string>(r.Matches(sb.ToString()).Cast <Match>().Select(x => x.Groups[1].Value), StringComparer.OrdinalIgnoreCase);
                foreach (var refPath in refFile.Value.OrderBy(x => x))
                {
                    var relativePath = FileHelpers.RelativePath(refFile.Key, refPath);
                    if (!existingPaths.Contains(relativePath))
                    {
                        write = true;
                        sb.AppendFormat("/// <reference path=\"{0}\" />\r\n", relativePath);
                    }
                }

                if (write)
                {
                    var fileResult = await FileHelpers.WriteAllTextRetry(refFile.Key, sb.ToString(), tgtProvider.EnsureFileIsWritable);

                    if (fileResult.ErrorMessage != null)
                    {
                        WriteMessage(fileResult.ErrorMessage);
                    }
                    resultFiles.Add(fileResult);
                }
            }
            WriteMessage("TS File Generation complete!");
            return(resultFiles);
        }
示例#8
0
 public TSWalker(SyntaxTree syntaxTree, TsOutputer output, TsContext context, SemanticModel model)
 {
     _csFile      = new CSharpFile(syntaxTree.FilePath);
     this.model   = model;
     this.context = context;
 }