diff --git a/DashTools.CodeGenerator/App.config b/DashTools.CodeGenerator/App.config new file mode 100644 index 0000000..44e1a77 --- /dev/null +++ b/DashTools.CodeGenerator/App.config @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/DashTools.CodeGenerator/ClassWalker.cs b/DashTools.CodeGenerator/ClassWalker.cs new file mode 100644 index 0000000..3ea4c2f --- /dev/null +++ b/DashTools.CodeGenerator/ClassWalker.cs @@ -0,0 +1,33 @@ +using Microsoft.CodeAnalysis.CSharp; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace DashTools.CodeGenerator +{ + public class ClassWalker : CSharpSyntaxWalker + { + public ClassWalker(SyntaxWalkerDepth depth = SyntaxWalkerDepth.Node) + : base(depth) + { + } + + public override void VisitClassDeclaration(ClassDeclarationSyntax node) + + { + var token = SyntaxFactory.Identifier( + node.Identifier.LeadingTrivia, + node.Identifier.Kind(), + node.Identifier.ValueText.Replace("type", ""), + node.Identifier.ValueText.Replace("type", ""), + node.Identifier.TrailingTrivia); + var changed = node.WithIdentifier(token); + + base.VisitClassDeclaration(node); + } + } +} diff --git a/DashTools.CodeGenerator/DashTools.CodeGenerator.csproj b/DashTools.CodeGenerator/DashTools.CodeGenerator.csproj new file mode 100644 index 0000000..f6e9f5d --- /dev/null +++ b/DashTools.CodeGenerator/DashTools.CodeGenerator.csproj @@ -0,0 +1,243 @@ + + + + + Debug + AnyCPU + {5B0225A5-45AE-4A44-9BC7-BF60825DFDF4} + Exe + Properties + DashTools.CodeGenerator + DashTools.CodeGenerator + v4.6.2 + 512 + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\Microsoft.Build.15.5.180\lib\net46\Microsoft.Build.dll + True + + + ..\packages\Microsoft.Build.Framework.15.5.180\lib\net46\Microsoft.Build.Framework.dll + True + + + ..\packages\Microsoft.Build.Tasks.Core.15.5.180\lib\net46\Microsoft.Build.Tasks.Core.dll + True + + + ..\packages\Microsoft.Build.Utilities.Core.15.5.180\lib\net46\Microsoft.Build.Utilities.Core.dll + True + + + ..\packages\Microsoft.CodeAnalysis.Common.2.6.1\lib\netstandard1.3\Microsoft.CodeAnalysis.dll + True + + + ..\packages\Microsoft.CodeAnalysis.CSharp.2.6.1\lib\netstandard1.3\Microsoft.CodeAnalysis.CSharp.dll + True + + + ..\packages\Microsoft.CodeAnalysis.CSharp.Workspaces.2.6.1\lib\netstandard1.3\Microsoft.CodeAnalysis.CSharp.Workspaces.dll + True + + + ..\packages\Microsoft.CodeAnalysis.VisualBasic.2.6.1\lib\netstandard1.3\Microsoft.CodeAnalysis.VisualBasic.dll + True + + + ..\packages\Microsoft.CodeAnalysis.VisualBasic.Workspaces.2.6.1\lib\netstandard1.3\Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll + True + + + ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.2.6.1\lib\net46\Microsoft.CodeAnalysis.Workspaces.dll + True + + + ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.2.6.1\lib\net46\Microsoft.CodeAnalysis.Workspaces.Desktop.dll + True + + + + ..\packages\System.AppContext.4.3.0\lib\net46\System.AppContext.dll + True + + + ..\packages\System.Collections.Immutable.1.3.1\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + True + + + + ..\packages\System.Composition.AttributedModel.1.0.31\lib\portable-net45+win8+wp8+wpa81\System.Composition.AttributedModel.dll + True + + + ..\packages\System.Composition.Convention.1.0.31\lib\portable-net45+win8+wp8+wpa81\System.Composition.Convention.dll + True + + + ..\packages\System.Composition.Hosting.1.0.31\lib\portable-net45+win8+wp8+wpa81\System.Composition.Hosting.dll + True + + + ..\packages\System.Composition.Runtime.1.0.31\lib\portable-net45+win8+wp8+wpa81\System.Composition.Runtime.dll + True + + + ..\packages\System.Composition.TypedParts.1.0.31\lib\portable-net45+win8+wp8+wpa81\System.Composition.TypedParts.dll + True + + + ..\packages\System.Console.4.3.0\lib\net46\System.Console.dll + True + + + + ..\packages\System.Diagnostics.FileVersionInfo.4.3.0\lib\net46\System.Diagnostics.FileVersionInfo.dll + True + + + ..\packages\System.Diagnostics.StackTrace.4.3.0\lib\net46\System.Diagnostics.StackTrace.dll + True + + + ..\packages\System.IO.Compression.4.3.0\lib\net46\System.IO.Compression.dll + True + + + ..\packages\System.IO.FileSystem.4.3.0\lib\net46\System.IO.FileSystem.dll + True + + + ..\packages\System.IO.FileSystem.Primitives.4.3.0\lib\net46\System.IO.FileSystem.Primitives.dll + True + + + + ..\packages\System.Reflection.4.3.0\lib\net462\System.Reflection.dll + True + + + ..\packages\System.Reflection.Metadata.1.4.2\lib\portable-net45+win8\System.Reflection.Metadata.dll + True + + + ..\packages\System.Runtime.4.3.0\lib\net462\System.Runtime.dll + True + + + ..\packages\System.Runtime.Extensions.4.3.0\lib\net462\System.Runtime.Extensions.dll + True + + + ..\packages\System.Runtime.InteropServices.4.3.0\lib\net462\System.Runtime.InteropServices.dll + True + + + ..\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll + True + + + ..\packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net461\System.Security.Cryptography.Algorithms.dll + True + + + ..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll + True + + + ..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll + True + + + ..\packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll + True + + + ..\packages\System.Text.Encoding.CodePages.4.3.0\lib\net46\System.Text.Encoding.CodePages.dll + True + + + ..\packages\System.Threading.Thread.4.3.0\lib\net46\System.Threading.Thread.dll + True + + + ..\packages\System.ValueTuple.4.3.0\lib\netstandard1.0\System.ValueTuple.dll + True + + + + + + + + + ..\packages\System.Xml.ReaderWriter.4.3.0\lib\net46\System.Xml.ReaderWriter.dll + True + + + ..\packages\System.Xml.XmlDocument.4.3.0\lib\net46\System.Xml.XmlDocument.dll + True + + + ..\packages\System.Xml.XPath.4.3.0\lib\net46\System.Xml.XPath.dll + True + + + ..\packages\System.Xml.XPath.XDocument.4.3.0\lib\net46\System.Xml.XPath.XDocument.dll + True + + + + + + + + + + + + + + + + + + + + + + + {d517b927-7afc-42ad-a410-27354f3217c2} + DashTools + + + + + \ No newline at end of file diff --git a/DashTools.CodeGenerator/MoveNamespacesToUsingsRewriter.cs b/DashTools.CodeGenerator/MoveNamespacesToUsingsRewriter.cs new file mode 100644 index 0000000..24eddec --- /dev/null +++ b/DashTools.CodeGenerator/MoveNamespacesToUsingsRewriter.cs @@ -0,0 +1,137 @@ +using Microsoft.CodeAnalysis.CSharp; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace DashTools.CodeGenerator +{ + public class MoveNamespacesToUsingsRewriter : CSharpSyntaxRewriter + { + private List namespacesToAdd = null; + + public MoveNamespacesToUsingsRewriter(bool visitIntoStructuredTrivia = false) + : base(visitIntoStructuredTrivia) + { + } + + public override SyntaxNode Visit(SyntaxNode node) + { + if (namespacesToAdd == null) + { + var finder = new UsingDirectivesFinder(); + finder.Visit(node); + var existingUsingDirectives = finder.ExistingUsingDirectives.ToList(); + namespacesToAdd = finder + .NamespacesInQualifiedNames + .Where(e => !existingUsingDirectives.Any(ee => ee.ToFullString() == e.ToFullString())) + .ToList(); + } + + node = base.Visit(node); + + return node; + } + + public override SyntaxNode VisitNamespaceDeclaration(NamespaceDeclarationSyntax node) + { + var usingsToAdd = namespacesToAdd + .Select(e => e.WithLeadingTrivia(SyntaxFactory.Whitespace(" "))) + .Select(e => SyntaxFactory.UsingDirective(e).WithLeadingTrivia(SyntaxFactory.Tab)) + .Select(e => e.WithTrailingTrivia(SyntaxFactory.CarriageReturnLineFeed)); + var newUsings = node.Usings.AddRange(usingsToAdd); + + return (base.VisitNamespaceDeclaration(node) as NamespaceDeclarationSyntax) + .WithUsings(new SyntaxList(newUsings)); + } + + public override SyntaxNode VisitAttribute(AttributeSyntax node) + { + node = base.VisitAttribute(node) as AttributeSyntax; + + if (node.Name is QualifiedNameSyntax) + { + var qualifiedName = node.Name as QualifiedNameSyntax; + var simpleName = qualifiedName.Right; + node = node.WithName(simpleName); + } + + return node; + } + + public override SyntaxNode VisitPropertyDeclaration(PropertyDeclarationSyntax node) + { + node = base.VisitPropertyDeclaration(node) as PropertyDeclarationSyntax; + + var type = GetTypeWithoutNamespaces(node.Type).WithTriviaFrom(node.Type); + node = node + .WithType(type) + .WithTriviaFrom(node); + + return node; + } + + public override SyntaxNode VisitFieldDeclaration(FieldDeclarationSyntax node) + { + node = base.VisitFieldDeclaration(node) as FieldDeclarationSyntax; + + var type = GetTypeWithoutNamespaces(node.Declaration.Type) + .WithTriviaFrom(node.Declaration.Type); + var declaration = node.Declaration + .WithType(type) + .WithTriviaFrom(node.Declaration); + node = node.WithDeclaration(declaration); + + return node; + } + + public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax node) + { + node = base.VisitMethodDeclaration(node) as MethodDeclarationSyntax; + + node = node.WithReturnType(GetTypeWithoutNamespaces(node.ReturnType)) + .WithLeadingTrivia(node.ReturnType.GetLeadingTrivia()) + .WithTrailingTrivia(node.ReturnType.GetTrailingTrivia()); + + + var parameters = node.ParameterList.Parameters; + for (int i = 0; i < parameters.Count; i++) + { + var arg = parameters[i]; + parameters = parameters.Replace( + arg, + arg.WithType(GetTypeWithoutNamespaces(arg.Type)) + .WithLeadingTrivia(arg.Type.GetLeadingTrivia()) + .WithTrailingTrivia(arg.Type.GetTrailingTrivia()) + ); + } + node = node.WithParameterList( + node.ParameterList + .WithParameters(parameters) + .WithLeadingTrivia(node.ParameterList.GetLeadingTrivia()) + .WithTrailingTrivia(node.ParameterList.GetTrailingTrivia()) + ); + + return node; + } + + private TypeSyntax GetTypeWithoutNamespaces(T type) + where T : TypeSyntax + { + QualifiedNameSyntax qualifiedName = null; + if (type is QualifiedNameSyntax) + { + qualifiedName = type as QualifiedNameSyntax; + } + else if (type is ArrayTypeSyntax && (type as ArrayTypeSyntax).ElementType is QualifiedNameSyntax) + { + qualifiedName = (type as ArrayTypeSyntax).ElementType as QualifiedNameSyntax; + } + + return qualifiedName?.Right as TypeSyntax ?? type; + } + } +} diff --git a/DashTools.CodeGenerator/MpdCodeRefactorer.cs b/DashTools.CodeGenerator/MpdCodeRefactorer.cs new file mode 100644 index 0000000..60d742f --- /dev/null +++ b/DashTools.CodeGenerator/MpdCodeRefactorer.cs @@ -0,0 +1,87 @@ +using Microsoft.CodeAnalysis.CSharp; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using System.Diagnostics; +using Microsoft.CodeAnalysis.Rename; + +namespace DashTools.CodeGenerator +{ + public class MpdCodeRefactorer : CSharpSyntaxRewriter + { + private readonly SemanticModel semanticModel; + + public RenameSymbolInfo Refactoring { get; private set; } + + public MpdCodeRefactorer(SemanticModel semanticModel, bool visitIntoStructuredTrivia = false) + : base(visitIntoStructuredTrivia) + { + this.semanticModel = semanticModel; + } + + public override SyntaxNode VisitClassDeclaration(ClassDeclarationSyntax node) + { + string className = node.Identifier.ValueText; + if (className.EndsWith("type")) + { + className = className.Replace("type", ""); + + Refactoring = new RenameSymbolInfo + { + Symbol = semanticModel.GetDeclaredSymbol(node), + NewName = className, + Comment = "Remove \"type\" suffix from class name" + }; + } + + return Refactoring == null + ? base.VisitClassDeclaration(node) + : node; + } + + public override SyntaxNode VisitPropertyDeclaration(PropertyDeclarationSyntax node) + { + string name = node.Identifier.ValueText; + if (name.Substring(0, 1) != name.Substring(0, 1).ToUpper()) + { + name = name.Substring(0, 1).ToUpper() + name.Substring(1); + + Refactoring = new RenameSymbolInfo + { + Symbol = semanticModel.GetDeclaredSymbol(node), + NewName = name, + Comment = "Capitalize property name's 1st letter" + }; + } + + return base.VisitPropertyDeclaration(node); + } + + public override SyntaxNode VisitFieldDeclaration(FieldDeclarationSyntax node) + { + foreach (var variable in node.Declaration.Variables) + { + string fieldName = variable.Identifier.ValueText; + if (fieldName.EndsWith("Field")) + { + fieldName = fieldName.Substring(0, fieldName.Length - "Field".Length); + + Refactoring = new RenameSymbolInfo + { + Symbol = semanticModel.GetDeclaredSymbol(variable), + NewName = fieldName, + Comment = "Remove \"Field\" suffix from field name" + }; + } + } + + return Refactoring == null + ? base.VisitFieldDeclaration(node) + : node; + } + } +} diff --git a/DashTools.CodeGenerator/Program.cs b/DashTools.CodeGenerator/Program.cs new file mode 100644 index 0000000..e66555a --- /dev/null +++ b/DashTools.CodeGenerator/Program.cs @@ -0,0 +1,184 @@ +using Microsoft.Build.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.Editing; +using Microsoft.CodeAnalysis.MSBuild; +using Microsoft.CodeAnalysis.Rename; +using Microsoft.CodeAnalysis.Text; +using System; +using System.CodeDom.Compiler; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Net; +using System.Text; +using System.Threading.Tasks; +using System.Xml.Serialization; + +namespace DashTools.CodeGenerator +{ + class Program + { + static void Main(string[] args) + { + try + { + MainAsync().Wait(); + } + catch (Exception ex) + { + Console.Write(ex); + } + + Console.WriteLine(); + Console.WriteLine("Press to exit"); + Console.ReadLine(); + } + + private static async Task MainAsync() + { + string filePath = await GenerateCodeForMpdSchema(); + string refactoredFilePath = await RefactorMpdCodeAsync(filePath); + + return; + + + + //var workspace = MSBuildWorkspace.Create(); + //var solution = await workspace.OpenSolutionAsync("../../../SharpDashTools.sln"); + //var project = solution.Projects.Single(p => p.AssemblyName == typeof(Qoollo.MpegDash.MpdDownloader).Assembly.GetName().Name); + //var document = project.Documents.Single(d => d.Name == "MpdSchema.cs"); + //var syntaxTree = await document.GetSyntaxRootAsync(); + + //var walker = new ClassWalker(); + //walker.Visit(syntaxTree); + + //var rewriter = new MpdCodeRefactorer(); + //var changed = rewriter.Visit(syntaxTree); + //File.WriteAllText(document.FilePath + "test.cs", changed.ToFullString()); + + //var generator = SyntaxGenerator.GetGenerator(workspace, LanguageNames.CSharp); + } + + private static async Task GenerateCodeForMpdSchema() + { + var schemaFiles = await DownloadMpdSchemaAsync(); + + string result = GenerateCodeForMpdSchema(schemaFiles); + + foreach (var file in schemaFiles) + File.Delete(file); + + return result; + } + + private static async Task DownloadMpdSchemaAsync() + { + const string xsdUrl = "https://github.com/Dash-Industry-Forum/Conformance-and-reference-source/raw/master/conformance/MPDValidator/schemas/DASH-MPD.xsd"; + const string xsdFile = "DASH-MPD.xsd"; + + const string xlinkUrl = "https://github.com/Dash-Industry-Forum/Conformance-and-reference-source/raw/master/conformance/MPDValidator/schemas/xlink.xsd"; + const string xlinkFile = "xlink.xsd"; + + var webClient = new WebClient(); + await webClient.DownloadFileTaskAsync(xsdUrl, xsdFile); + await webClient.DownloadFileTaskAsync(xlinkUrl, xlinkFile); + + return new[] { xsdFile, xlinkFile }; + } + + private static string GenerateCodeForMpdSchema(IEnumerable xsdFiles) + { + const string xsdExePath = @"C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools\xsd.exe"; + if (!File.Exists(xsdExePath)) + throw new InvalidOperationException("xsd.exe not found at " + xsdExePath); + + const string newFileName = "MpdSchema.cs"; + if (File.Exists(newFileName)) + File.Delete(newFileName); + + var process = Process.Start(xsdExePath, string.Join(" ", xsdFiles) + " /c /n:Qoollo.MpegDash"); + if (!process.WaitForExit(20000)) + throw new TimeoutException("XSD -> C# code generation takes too long. Something's wrong."); + + string fileName = string.Join("_", xsdFiles.Select(e => Path.GetFileNameWithoutExtension(e))) + ".cs"; + if (!File.Exists(fileName)) + throw new Exception("XSD -> C# code generation succeeded, but file " + fileName + " was not found"); + + File.Move(fileName, newFileName); + + return newFileName; + } + + private static async Task RefactorMpdCodeAsync(string filePath) + { + var workspace = new AdhocWorkspace(); + var projectId = ProjectId.CreateNewId(); + var versionStamp = VersionStamp.Create(); + var projectInfo = ProjectInfo.Create(projectId, versionStamp, "test", "test", LanguageNames.CSharp); + projectInfo = projectInfo.WithMetadataReferences( + new [] + { + typeof(int), + typeof(object), + typeof(GeneratedCodeAttribute), + typeof(XmlTypeAttribute) + } + .Select(e => e.Assembly.Location) + .Select(e => MetadataReference.CreateFromFile(e)) + ); + var project = workspace.AddProject(projectInfo); + + var sourceText = SourceText.From(File.ReadAllText(filePath)); + var document = workspace.AddDocument(project.Id, "NewFile.cs", sourceText); + var syntaxRoot = await document.GetSyntaxRootAsync(); + + + var semanticModel = await document.GetSemanticModelAsync(); + var diagnostics = semanticModel.GetDiagnostics(); + + var rewriters = new CSharpSyntaxRewriter[] + { + new MoveNamespacesToUsingsRewriter(), + new RemoveAttributeSuffixRewriter() + }; + foreach (var rewriter in rewriters) + { + syntaxRoot = rewriter.Visit(syntaxRoot); + + workspace.TryApplyChanges(workspace.CurrentSolution.WithDocumentSyntaxRoot(document.Id, syntaxRoot)); + document = workspace.CurrentSolution.GetDocument(document.Id); + syntaxRoot = await document.GetSyntaxRootAsync(); + semanticModel = await document.GetSemanticModelAsync(); + } + + var refactorer = new MpdCodeRefactorer(semanticModel); + syntaxRoot = await document.GetSyntaxRootAsync(); + syntaxRoot = refactorer.Visit(syntaxRoot); + while (refactorer.Refactoring != null) + { + diagnostics = semanticModel.GetDiagnostics(); + + var solution = await Renamer.RenameSymbolAsync(workspace.CurrentSolution, refactorer.Refactoring.Symbol, refactorer.Refactoring.NewName, workspace.Options); + if (!workspace.TryApplyChanges(solution)) + { + throw new InvalidOperationException("Failed to apply changes after rename"); + } + Console.WriteLine("Applied refactoring:\n\t{0}", refactorer.Refactoring); + + document = workspace.CurrentSolution.GetDocument(document.Id); + syntaxRoot = await document.GetSyntaxRootAsync(); + semanticModel = await document.GetSemanticModelAsync(); + refactorer = new MpdCodeRefactorer(semanticModel); + refactorer.Visit(syntaxRoot); + } + + const string newFileName = "NewFileRefactored.cs"; + File.WriteAllText(newFileName, syntaxRoot.ToFullString()); + + return newFileName; + } + + } +} diff --git a/DashTools.CodeGenerator/Properties/AssemblyInfo.cs b/DashTools.CodeGenerator/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..4a145b2 --- /dev/null +++ b/DashTools.CodeGenerator/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("DashTools.CodeGenerator")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("DashTools.CodeGenerator")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("5b0225a5-45ae-4a44-9bc7-bf60825dfdf4")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/DashTools.CodeGenerator/RemoveAttributeSuffixRewriter.cs b/DashTools.CodeGenerator/RemoveAttributeSuffixRewriter.cs new file mode 100644 index 0000000..0fece2c --- /dev/null +++ b/DashTools.CodeGenerator/RemoveAttributeSuffixRewriter.cs @@ -0,0 +1,64 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace DashTools.CodeGenerator +{ + public class RemoveAttributeSuffixRewriter : CSharpSyntaxRewriter + { + public RemoveAttributeSuffixRewriter(bool visitIntoStructuredTrivia = false) + : base(visitIntoStructuredTrivia) + { + } + + public override SyntaxNode VisitAttribute(AttributeSyntax node) + { + node = base.VisitAttribute(node) as AttributeSyntax; + + if (node.Name is QualifiedNameSyntax) + { + var qualifiedName = node.Name as QualifiedNameSyntax; + var newRight = RemoveTrailingAttributeFromName(qualifiedName.Right); + var newQualifiedName = qualifiedName.WithRight(newRight); + node = node.WithName(newQualifiedName); + } + else if (node.Name is SimpleNameSyntax) + { + var newName = RemoveTrailingAttributeFromName(node.Name as SimpleNameSyntax); + node = node.WithName(newName); + } + else if (Debugger.IsAttached) + { + Debugger.Break(); + } + + return node; + } + + private SimpleNameSyntax RemoveTrailingAttributeFromName(SimpleNameSyntax simpleName) + { + string attributeName = simpleName.Identifier.ValueText; + if (attributeName.EndsWith("Attribute")) + { + attributeName = attributeName.Substring(0, attributeName.Length - "Attribute".Length); + + var identifier = SyntaxFactory.Identifier( + simpleName.Identifier.LeadingTrivia, + simpleName.Identifier.Kind(), + attributeName, + attributeName, + simpleName.Identifier.TrailingTrivia + ); + simpleName = simpleName.WithIdentifier(identifier); + } + + return simpleName; + } + } +} diff --git a/DashTools.CodeGenerator/RenameSymbolInfo.cs b/DashTools.CodeGenerator/RenameSymbolInfo.cs new file mode 100644 index 0000000..7544f22 --- /dev/null +++ b/DashTools.CodeGenerator/RenameSymbolInfo.cs @@ -0,0 +1,18 @@ +using Microsoft.CodeAnalysis; + +namespace DashTools.CodeGenerator +{ + public class RenameSymbolInfo + { + public ISymbol Symbol { get; set; } + + public string NewName { get; set; } + + public string Comment { get; set; } + + public override string ToString() + { + return $"{Comment}.\n\tOld name: {Symbol.Name}.\n\tNew name: {NewName}."; + } + } +} \ No newline at end of file diff --git a/DashTools.CodeGenerator/UsingDirectivesFinder.cs b/DashTools.CodeGenerator/UsingDirectivesFinder.cs new file mode 100644 index 0000000..c98fd08 --- /dev/null +++ b/DashTools.CodeGenerator/UsingDirectivesFinder.cs @@ -0,0 +1,104 @@ +using Microsoft.CodeAnalysis.CSharp; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace DashTools.CodeGenerator +{ + public class UsingDirectivesFinder : CSharpSyntaxWalker + { + public IEnumerable ExistingUsingDirectives + { + get { return existingUsingDirectives; } + } + private readonly List existingUsingDirectives = new List(); + + public IEnumerable NamespacesInQualifiedNames + { + get { return namespacesInQualifiedNames; } + } + private readonly List namespacesInQualifiedNames = new List(); + + public override void VisitUsingDirective(UsingDirectiveSyntax node) + { + base.VisitUsingDirective(node); + + if (!existingUsingDirectives.Any(e => e.ToFullString() == node.Name.ToFullString())) + existingUsingDirectives.Add(node.Name); + } + + public override void VisitAttribute(AttributeSyntax node) + { + base.VisitAttribute(node); + + if (node.Name is QualifiedNameSyntax) + { + var qualifiedName = node.Name as QualifiedNameSyntax; + if (!namespacesInQualifiedNames.Any(e => e.ToFullString() == qualifiedName.Left.ToFullString())) + { + namespacesInQualifiedNames.Add(qualifiedName.Left); + } + } + } + + public override void VisitPropertyDeclaration(PropertyDeclarationSyntax node) + { + base.VisitPropertyDeclaration(node); + + ProcessType(node.Type); + } + + public override void VisitFieldDeclaration(FieldDeclarationSyntax node) + { + base.VisitFieldDeclaration(node); + + ProcessType(node.Declaration.Type); + } + + public override void VisitMethodDeclaration(MethodDeclarationSyntax node) + { + base.VisitMethodDeclaration(node); + + ProcessType(node.ReturnType); + + foreach (var arg in node.ParameterList.Parameters) + { + ProcessType(arg.Type); + } + } + + private void ProcessType(TypeSyntax type) + { + var qualifiedNames = new List(); + + if (type is IdentifierNameSyntax) + { + // (type as IdentifierNameSyntax).Identifier + } + else if (type is ArrayTypeSyntax) + { + var elementType = (type as ArrayTypeSyntax).ElementType; + if (elementType is QualifiedNameSyntax) + { + qualifiedNames.Add(elementType as QualifiedNameSyntax); + } + } + else if (type is QualifiedNameSyntax) + { + qualifiedNames.Add(type as QualifiedNameSyntax); + } + + foreach (var qualifiedName in qualifiedNames) + { + if (!namespacesInQualifiedNames.Any(e => e.ToFullString() == qualifiedName.Left.ToFullString())) + { + namespacesInQualifiedNames.Add(qualifiedName.Left); + } + } + } + + } +} diff --git a/DashTools.CodeGenerator/packages.config b/DashTools.CodeGenerator/packages.config new file mode 100644 index 0000000..bb7ca56 --- /dev/null +++ b/DashTools.CodeGenerator/packages.config @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/DashTools.Samples/Program.cs b/DashTools.Samples/Program.cs index 73df624..fe443ae 100644 --- a/DashTools.Samples/Program.cs +++ b/DashTools.Samples/Program.cs @@ -11,6 +11,16 @@ namespace Qoollo.MpegDash.Samples { class Program { + private static readonly string[] mpdFiles = new string[] + { + "http://ncplusgo.s43-po.live.e56-po.insyscd.net/out/u/eskatvsd.mpd", + "http://dash.edgesuite.net/envivio/EnvivioDash3/manifest.mpd", + "http://dash.edgesuite.net/dash264/TestCases/1a/netflix/exMPD_BIP_TC1.mpd", + "http://10.5.5.7/q/p/userapi/streams/32/mpd", + "http://10.5.7.207/userapi/streams/30/mpd", + "http://10.5.7.207/userapi/streams/11/mpd?start_time=1458816642&stop_time=1458819642", + }; + static void Main(string[] args) { Task.Run(async () => @@ -22,11 +32,9 @@ static void Main(string[] args) static async Task MainAsync(string[] args) { string dir = "envivio"; - string mpdUrl = "http://10.5.5.7/q/p/userapi/streams/32/mpd"; - //"http://10.5.7.207/userapi/streams/30/mpd"; - //"http://10.5.7.207/userapi/streams/11/mpd?start_time=1458816642&stop_time=1458819642"; - //"http://dash.edgesuite.net/envivio/EnvivioDash3/manifest.mpd"; - //"http://dash.edgesuite.net/dash264/TestCases/1a/netflix/exMPD_BIP_TC1.mpd"; + string mpdUrl = mpdFiles[0]; + var from = TimeSpan.Zero; + var to = TimeSpan.MaxValue; var stopwatch = Stopwatch.StartNew(); var downloader = new MpdDownloader(new Uri(mpdUrl), dir); @@ -39,7 +47,7 @@ static async Task MainAsync(string[] args) // ? new Mp4InitFile(Path.Combine("envivio", Path.GetFileName(f))) // : new Mp4File(Path.Combine("envivio", Path.GetFileName(f)))) // .ToArray(); - await downloader.Download(trackRepresentation, TimeSpan.FromMinutes(60), TimeSpan.FromMinutes(60 + 60 * 6 / 6)); + await downloader.Download(trackRepresentation, from, to); var downloadTime = stopwatch.Elapsed - prepareTime; var ffmpeg = new FFMpegConverter(); diff --git a/DashTools/DashTools.csproj b/DashTools/DashTools.csproj index e77fcdb..77779c6 100644 --- a/DashTools/DashTools.csproj +++ b/DashTools/DashTools.csproj @@ -40,6 +40,8 @@ + + @@ -54,16 +56,23 @@ + + + + + + +