Exemplo n.º 1
0
        public static async Task <LazinatorCompilationAnalyzer> CreateCompilationAnalyzer(Compilation compilation,
                                                                                          CancellationToken cancellationToken, ImmutableArray <TextDocument> additionalFiles)
        {
            // Check if the attribute type LazinatorAttribute is defined.
            INamedTypeSymbol lazinatorAttributeType = compilation.GetTypeByMetadataName(LazinatorAttributeName);

            if (lazinatorAttributeType == null)
            {
                return(null);
            }

            // Check if the interface type ILazinator is defined.
            INamedTypeSymbol lazinatorInterfaceType = compilation.GetTypeByMetadataName(LazinatorInterfaceName);

            if (lazinatorInterfaceType == null)
            {
                return(null);
            }

            (string configPath, string configString) = await LazinatorConfigLoader.GetConfigPathAndText(additionalFiles, cancellationToken);

            LazinatorConfig config = new LazinatorConfig(configPath, configString);

            // Initialize state in the start action.
            var analyzer = new LazinatorCompilationAnalyzer(lazinatorAttributeType, lazinatorInterfaceType, configPath, configString, config);

            return(analyzer);
        }
Exemplo n.º 2
0
 public LazinatorCompilationAnalyzer(INamedTypeSymbol lazinatorAttributeType, INamedTypeSymbol lazinatorInterfaceType, string configPath, string configString, LazinatorConfig config)
 {
     _lazinatorAttributeType = lazinatorAttributeType;
     _lazinatorInterfaceType = lazinatorInterfaceType;
     // we pass information about the config as well as the config itself, since we need to use the config, but also need to pass information about it to the code fix provider
     _configPath   = configPath;
     _configString = configString;
     _config       = config;
 }
Exemplo n.º 3
0
        public void CanJsonDeserializeConfigFile2()
        {
            string          configString = @"
                {
                  ""InterchangeConverters"": {
                    ""LazinatorTests.Examples.NonLazinatorInterchangeableClass"": ""LazinatorTests.Examples.NonLazinatorInterchangeClass""
                  }
                }";
            LazinatorConfig config       = new LazinatorConfig(null, configString);

            config.InterchangeConverters["LazinatorTests.Examples.NonLazinatorInterchangeableClass"].Should().Be("LazinatorTests.Examples.NonLazinatorInterchangeClass");
        }
Exemplo n.º 4
0
        public void CanJsonDeserializeConfigFile()
        {
            string          configString = @"
                {
                  ""InterchangeConverters"": {
                    ""MyNamespace.A"": ""AnotherNamespace.A_Interchange"",
                    ""MyNamespace.B"": ""AnotherNamespace.B_Interchange""
                  }
                }";
            LazinatorConfig config       = new LazinatorConfig(null, configString);

            config.InterchangeConverters["MyNamespace.A"].Should().Be("AnotherNamespace.A_Interchange");
            config.InterchangeConverters["MyNamespace.B"].Should().Be("AnotherNamespace.B_Interchange");
        }
Exemplo n.º 5
0
        public LazinatorConfig LoadLazinatorConfig()
        {
            LazinatorConfig config = null;

            if (Config != null && Config != "")
            {
                try
                {
                    config = new LazinatorConfig(ConfigPath, Config);
                }
                catch
                {
                    throw new LazinatorCodeGenException("Lazinator.config is not a valid JSON file.");
                }
            }

            return(config);
        }
Exemplo n.º 6
0
        private static LazinatorConfig FindConfigFileStartingFromSubfolder(string mainFolder, string subfolder, string projectPath)
        {
            ReadCodeFile.GetCodeInFile(projectPath, mainFolder, subfolder, "LazinatorConfig", ".json", out string configPath, out string configText);
            if (configText == null)
            {
                ReadCodeFile.GetCodeInFile(projectPath, mainFolder, "/", "LazinatorConfig", ".json", out configPath, out configText);
            }
            if (configText == null)
            {
                ReadCodeFile.GetCodeInFile(projectPath, "/", "", "LazinatorConfig", ".json", out configPath, out configText);
            }
            LazinatorConfig config = null;

            if (configText != null)
            {
                config = JsonConvert.DeserializeObject <LazinatorConfig>(configText);
            }
            return(config);
        }
Exemplo n.º 7
0
        private static async Task CompleteGenerateCode(Type existingType, string project, string mainFolder, string subfolder, AdhocWorkspace ws)
        {
            if (mainFolder == "" && subfolder == "")
            {
                mainFolder = "/";
            }
            if (existingType.IsInterface)
            {
                throw new Exception("Can complete generate code only on class implementing interface, not interface itself.");
            }
            string projectPath = ReadCodeFile.GetCodeBasePath(project);
            string name        = ReadCodeFile.GetNameOfType(existingType);

            ReadCodeFile.GetCodeInFile(projectPath, mainFolder, subfolder, name, ".g.cs", out string codeBehindPath, out string codeBehind);
            LazinatorConfig config = FindConfigFileStartingFromSubfolder(mainFolder, subfolder, projectPath);

            // uncomment to include tracing code
            //if (config == null)
            //    config = new LazinatorConfig();
            //config.IncludeTracingCode = true;

            var compilation = await AdhocWorkspaceManager.GetCompilation(ws);

            LazinatorCompilation lazinatorCompilation = new LazinatorCompilation(compilation, existingType, config);

            var  d      = new ObjectDescription(lazinatorCompilation.ImplementingTypeSymbol, lazinatorCompilation, codeBehindPath, true);
            var  result = d.GetCodeBehind();
            bool match  = codeBehind == result;

            // return; // uncomment this to prevent any changes to classes during testing if automaticallyFix is true

            bool automaticallyFix = true; // Set to true to automatically update all test classes on the local development machine to a new format. This will trivially result in the test passing. Before doing this, submit all changes. After doing this, if code compiles, run all tests. Then set this back to false.

            if (automaticallyFix && !match)
            {
                File.WriteAllText(codeBehindPath, result);
            }
            else
            {
                match.Should().BeTrue();
            }
        }
Exemplo n.º 8
0
        public static (Location codeBehindLocation, List <Location> incorrectCodeBehindLocations, List <Location> lazinatorObjectLocationsExcludingCodeBehind) CategorizeLocations(LazinatorConfig config, INamedTypeSymbol lazinatorObject, List <Location> mainTypeLocations)
        {
            string generatedCodeFileExtension = config?.GeneratedCodeFileExtension ?? ".laz.cs";
            bool   useFullyQualifiedNames     = (config?.UseFullyQualifiedNames ?? false) || lazinatorObject.ContainingType != null || lazinatorObject.IsGenericType;
            string correctCodeBehindName      = RoslynHelpers.GetEncodableVersionOfIdentifier(lazinatorObject, useFullyQualifiedNames) + generatedCodeFileExtension;
            var    nonGeneratedLocations      = mainTypeLocations.Where(x => !x.SourceTree.FilePath.EndsWith(generatedCodeFileExtension)).ToList();
            var    codeBehindLocations        = mainTypeLocations.Where(x => x.SourceTree.FilePath.EndsWith(generatedCodeFileExtension)).ToList();
            IEnumerable <Location> possiblyCorrectCodeBehindLocations = mainTypeLocations.Where(x => x.SourceTree.FilePath.EndsWith(correctCodeBehindName));
            Location        codeBehindLocation           = possiblyCorrectCodeBehindLocations.FirstOrDefault();
            List <Location> incorrectCodeBehindLocations = codeBehindLocations.Where(x => x != codeBehindLocation).ToList();

            return(codeBehindLocation, incorrectCodeBehindLocations, nonGeneratedLocations);
        }
Exemplo n.º 9
0
        private void CategorizeLocations(IReadOnlyList <Location> locations)
        {
            LazinatorConfig config = LoadLazinatorConfig();

            (CodeBehindLocation, IncorrectCodeBehindLocations, LazinatorObjectLocationsExcludingCodeBehind) = CategorizeLocations(config, LazinatorObject, new List <Location>(locations));
        }
Exemplo n.º 10
0
        public static async Task <Solution> AttemptFixGenerateLazinatorCodeBehind(Document originalDocument, LazinatorPairInformation lazinatorPairInformation, CancellationToken cancellationToken)
        {
            var             originalSolution = originalDocument.Project.Solution;
            LazinatorConfig config           = lazinatorPairInformation.LoadLazinatorConfig();

            var semanticModel = await originalDocument.GetSemanticModelAsync(cancellationToken);

            LazinatorCompilation generator = null;

            if (!RecycleLazinatorCompilation || _LastLazinatorCompilation == null)
            {
                generator = new LazinatorCompilation(semanticModel.Compilation, lazinatorPairInformation.LazinatorObject.Name, lazinatorPairInformation.LazinatorObject.GetFullMetadataName(), config);
                if (RecycleLazinatorCompilation)
                {
                    _LastLazinatorCompilation = generator;
                }
            }
            else
            {
                generator = _LastLazinatorCompilation;
                generator.Initialize(semanticModel.Compilation, lazinatorPairInformation.LazinatorObject.Name, lazinatorPairInformation.LazinatorObject.GetFullMetadataName());
            }
            var d          = new ObjectDescription(generator.ImplementingTypeSymbol, generator, originalDocument.FilePath);
            var codeBehind = d.GetCodeBehind();

            string fileExtension      = config?.GeneratedCodeFileExtension ?? ".laz.cs";
            var    project            = originalDocument.Project;
            string codeBehindFilePath = null;
            string codeBehindName     = null;

            string[] codeBehindFolders      = null;
            bool     useFullyQualifiedNames = (config?.UseFullyQualifiedNames ?? false) || generator.ImplementingTypeSymbol.ContainingType != null || generator.ImplementingTypeSymbol.IsGenericType;

            codeBehindName = RoslynHelpers.GetEncodableVersionOfIdentifier(generator.ImplementingTypeSymbol, useFullyQualifiedNames) + fileExtension;

            string[] GetFolders(string fileName)
            {
                return(fileName.Split('\\', '/').Where(x => !x.Contains(".cs") && !x.Contains(".csproj")).ToArray());
            }

            if (config?.GeneratedCodePath == null)
            { // use short form of name in same location as original code
                codeBehindFilePath = originalDocument.FilePath;
                codeBehindFolders  = GetFolders(codeBehindFilePath).Skip(GetFolders(originalDocument.Project.FilePath).Count()).ToArray();
            }
            else
            { // we have a config file specifying a common directory
                codeBehindFilePath = config.GeneratedCodePath;
                if (!codeBehindFilePath.EndsWith("\\"))
                {
                    codeBehindFilePath += "\\";
                }
                codeBehindFolders = config.RelativeGeneratedCodePath.Split('\\', '/');
            }
            codeBehindFilePath = System.IO.Path.GetDirectoryName(codeBehindFilePath);
            while (codeBehindFilePath.EndsWith(".cs"))
            {
                var lastSlash = codeBehindFilePath.IndexOfAny(new char[] { '\\', '/' });
                if (lastSlash >= 0)
                {
                    codeBehindFilePath = codeBehindFilePath.Substring(0, lastSlash);
                }
            }
            while (codeBehindFilePath.EndsWith("\\"))
            {
                codeBehindFilePath = codeBehindFilePath.Substring(0, codeBehindFilePath.Length - 1);
            }
            codeBehindFilePath += "\\" + codeBehindName;

            Solution revisedSolution;

            if (lazinatorPairInformation.CodeBehindLocation == null)
            { // The file does not already exist
              // codeBehindFilePath = System.IO.Path.GetDirectoryName(codeBehindFilePath); // omit file name
                Document documentToAdd = project.AddDocument(codeBehindName, codeBehind, codeBehindFolders, codeBehindFilePath);
                //if (config.GeneratedCodePath != null)
                //    documentToAdd = documentToAdd.WithFolders(codeBehindFolders);
                revisedSolution = documentToAdd.Project.Solution;
            }
            else
            { // the file does already exist
                var currentDocumentWithCode = originalSolution.GetDocument(lazinatorPairInformation.CodeBehindLocation.SourceTree);
                var replacementDocument     = currentDocumentWithCode.WithText(SourceText.From(codeBehind));
                revisedSolution = originalSolution.WithDocumentText(currentDocumentWithCode.Id, SourceText.From(codeBehind));
            }
            revisedSolution = await AddAnnotationToIndicateSuccess(revisedSolution, true);

            return(revisedSolution);
        }