public void SharedSourceFiles_Methods()
        {
            string projectPath = null;
            string outputPath = null;
            TestHelper.GetProjectPaths("SFT", out projectPath, out outputPath);
            string clientProjectPath = CodeGenHelper.ClientClassLibProjectPath(projectPath);
            List<string> sourceFiles = CodeGenHelper.ClientClassLibSourceFiles(clientProjectPath);
            ConsoleLogger logger = new ConsoleLogger();
            FilenameMap filenameMap = new FilenameMap();

            using (SourceFileLocationService locationService = new SourceFileLocationService(new[] { new PdbSourceFileProviderFactory(/*symbolSearchPath*/ null, logger) }, filenameMap))
            {
                SharedSourceFiles ssf = new SharedSourceFiles(locationService, filenameMap, sourceFiles);

                int[] fileIds = ssf.GetSharedFileIds(CodeMemberKey.CreateMethodKey(typeof(TestValidator).GetMethod("IsValid")));
                Assert.IsNotNull(fileIds, "Expected TestValidator.IsValid to have non-null file ID's because it is shared");
                Assert.AreEqual(1, fileIds.Length, "Expected TestValidator.IsValid to be found in exactly one file");
                Assert.IsTrue(filenameMap[fileIds[0]].Contains("TestValidator.linked.cs"), "Expected TestValidator.IsValid to be in TestValidator.linked.cs");

                fileIds = ssf.GetSharedFileIds(CodeMemberKey.CreateMethodKey(typeof(TestEntity).GetMethod("ServerAndClientMethod")));
                Assert.IsNotNull(fileIds, "Expected TestEntity.ServerAndClientMethod to have non-null file ID's because it is shared");
                Assert.AreEqual(1, fileIds.Length, "Expected TestEntity.ServerAndClientMethod to be found in exactly one file");
                Assert.IsTrue(filenameMap[fileIds[0]].Contains("TestEntity.linked.cs"), "Expected TestEntity.ServerAndClientMethod to be in TestEntity.linked.cs");

                fileIds = ssf.GetSharedFileIds(CodeMemberKey.CreateMethodKey(typeof(TestEntity).GetMethod("ServerMethod")));
                Assert.IsNull(fileIds, "Expected TestEntity.ServerMethod to have null file ids");

                fileIds = ssf.GetSharedFileIds(CodeMemberKey.CreateMethodKey(typeof(TestValidatorServer).GetMethod("IsValid")));
                Assert.IsNull(fileIds, "Expected TestValidatorServer.IsValid to have null file ids");
            }
        }
        public void Multiple_Providers_Preserve_Order()
        {
            long createCountBefore = Interlocked.Read(ref MockSourceFileProviderFactory.createCount);

            // This func returns a file name only for the StringValue property
            Func<MemberInfo, string> func1 = m => { return m.Name == "StringValue" ? m.Name : null; };

            // The second func returns "IntValue" but also a contradictory name XXX for StringValue.
            // We are testing the preservation of order here in that only one service is allowed to
            // declare a file for a single MemberInfo, and the first one wins
            Func<MemberInfo, string> func2 = m => { return m.Name == "IntValue" ? m.Name : m.Name == "StringValue" ? "XXX" : null; };

            MockSourceFileProviderFactory factory1 = new MockSourceFileProviderFactory(func1);
            MockSourceFileProviderFactory factory2 = new MockSourceFileProviderFactory(func2);

            FilenameMap filenameMap = new FilenameMap();

            using (SourceFileLocationService locationService = new SourceFileLocationService(new[] { factory1, factory2 }, filenameMap))
            {
                IEnumerable<string> files = locationService.GetFilesForType(typeof(SourceFileLocationServiceTest));
                Assert.AreEqual(2, files.Count(), "Expected both service to contribute to files");
                Assert.IsTrue(files.Contains("StringValue"), "The first service should have gotten called");
                Assert.IsTrue(files.Contains("IntValue"), "The second service should have gotten called");
                Assert.IsFalse(files.Contains("XXX"), "The 2nd response to StringValue should be discarded");
            }

            long createCountAfter = Interlocked.Read(ref MockSourceFileProviderFactory.createCount);
            Assert.AreEqual(createCountBefore, createCountAfter, "Imbalanced create/dispose count of ISourceFileProviders");
        }
        public void SharedSourceFiles_Types()
        {
            string projectPath = null;
            string outputPath = null;
            TestHelper.GetProjectPaths("SFT", out projectPath, out outputPath);
            string clientProjectPath = CodeGenHelper.ClientClassLibProjectPath(projectPath);
            List<string> sourceFiles = CodeGenHelper.ClientClassLibSourceFiles(clientProjectPath);
            ConsoleLogger logger = new ConsoleLogger();
            FilenameMap filenameMap = new FilenameMap();

            using (SourceFileLocationService locationService = new SourceFileLocationService(new[] { new PdbSourceFileProviderFactory(/*symbolSearchPath*/ null, logger) }, filenameMap))
            {
                SharedSourceFiles ssf = new SharedSourceFiles(locationService, filenameMap, sourceFiles);

                int[] fileIds = ssf.GetSharedFileIds(CodeMemberKey.CreateTypeKey(typeof(TestEntity)));
                Assert.IsNotNull(fileIds, "Expected TestEntity to have non-null file ID's because it is shared");
                Assert.AreEqual(2, fileIds.Length, "Expected TestEntity to be found in exactly 2 files");
                foreach (int i in fileIds)
                {
                    string file = filenameMap[i];
                    Assert.IsTrue(file.Contains("TestEntity.linked.cs") || file.Contains("TestEntity.reverse.linked.cs"), "Expected exactly these 2 files to be shared");
                }

                fileIds = ssf.GetSharedFileIds(CodeMemberKey.CreateTypeKey(typeof(TestValidator)));
                Assert.IsNotNull(fileIds, "Expected TestValidator to have non-null file ID's because it is shared");
                Assert.AreEqual(1, fileIds.Length, "Expected TestValidator to be found in exactly one file");
                Assert.IsTrue(filenameMap[fileIds[0]].Contains("TestValidator.linked.cs"), "expected this to be the sole shared file for TestValidator");

                fileIds = ssf.GetSharedFileIds(CodeMemberKey.CreateTypeKey(typeof(DomainService)));
                Assert.IsNull(fileIds, "Expected DomainService to have no shared file ids");

                fileIds = ssf.GetSharedFileIds(CodeMemberKey.CreateTypeKey(typeof(TestValidatorServer)));
                Assert.IsNull(fileIds, "Expected DomainService to have no shared file ids");
            }
        }
 public void Dispose()
 {
     if (this._locationService != null)
     {
         this._locationService.Dispose();
         this._locationService = null;
     }
     this._filenameMap = null;
 }
        /// <summary>
        /// Initializes a new <see cref="SourceFileLocationService"/> instance.
        /// </summary>
        /// <param name="providerFactories">Ordered set of factories that can supply <see cref="ISourceFileProvider"/>
        /// instances to perform implementation-specific file location.
        /// </param>
        /// <param name="filenameMap">A file name to ID mapping cache to use to keep file names as integer ID's.
        /// </param>
        internal SourceFileLocationService(IEnumerable <ISourceFileProviderFactory> providerFactories, FilenameMap filenameMap)
        {
            Debug.Assert(providerFactories != null && providerFactories.Any(), "providerFactories are required");
            Debug.Assert(filenameMap != null, "filenameMap is required");

            this._filenameMap = filenameMap;

            // Get the provider from each factory, and store our ordered list of providers
            this._providers = providerFactories.Select(f => f.CreateProvider()).ToArray();
        }
        /// <summary>
        /// Initializes a new <see cref="SourceFileLocationService"/> instance.
        /// </summary>
        /// <param name="providerFactories">Ordered set of factories that can supply <see cref="ISourceFileProvider"/>
        /// instances to perform implementation-specific file location.
        /// </param>
        /// <param name="filenameMap">A file name to ID mapping cache to use to keep file names as integer ID's.
        /// </param>
        internal SourceFileLocationService(IEnumerable<ISourceFileProviderFactory> providerFactories, FilenameMap filenameMap)
        {
            Debug.Assert(providerFactories != null && providerFactories.Count() > 0, "providerFactories are required");
            Debug.Assert(filenameMap != null, "filenameMap is required");

            this._filenameMap = filenameMap;

            // Get the provider from each factory, and store our ordered list of providers
            this._providers = providerFactories.Select(f => f.CreateProvider()).ToArray();
        }
        public void FilenameMap_Ctor()
        {
            FilenameMap cache = new FilenameMap();
            int id = cache[string.Empty];
            Assert.AreEqual(FilenameMap.NotAFile, id, "expected empty string to be cached as NotAFile");

            string file = cache[id];
            Assert.AreEqual(string.Empty, file, "Expected cache[0] to be empty string");

            id = cache.AddOrGet(string.Empty);
            Assert.AreEqual(FilenameMap.NotAFile, id, "adding back string.Empty should be same ID");
        }
        public void FilenameMap_Case_Insensitive()
        {
            FilenameMap cache = new FilenameMap();
            int id1 = cache.AddOrGet("test");
            Assert.AreNotEqual(FilenameMap.NotAFile, id1, "actual ID cannot be NotAFile");

            int id2 = cache.AddOrGet("TeSt");
            Assert.AreEqual(id1, id2, "add should return same ID for files differing only in case");

            Assert.AreEqual(id1, cache["test"], "indexer should return same ID as add");
            Assert.AreEqual(id1, cache["tESt"], "indexer should return same ID as add differing in case");

            Assert.AreEqual("test", cache[id1], "cache should not have overwritten original");
        }
        public void Mock_SourceFileLocationService_Works()
        {
            MethodBase methodBase = MethodBase.GetCurrentMethod();

            // We will generate a fake file name for the request of the currently executing method
            // This tests whether MemberInfo equality is a good mechanism and shows the basic
            // plumbing of the abstract base class works
            Func<MemberInfo, string> func = m => { return m.Equals(methodBase) ? m.Name : null; };
            FilenameMap filenameMap = new FilenameMap();

            using (SourceFileLocationService service = new SourceFileLocationService(new[] { new MockSourceFileProviderFactory(func) }, filenameMap))
            {
                IEnumerable<string> files = service.GetFilesForType(this.GetType());
                Assert.AreEqual(1, files.Count(), "Expected only one file name");
                Assert.IsTrue(files.Contains(methodBase.Name), "Expected the name of the current method to be returned for the declaring type");
            }
        }
        public void PdbReader_Finds_Types_Files()
        {
            string projectPath = null;
            string outputPath = null;
            TestHelper.GetProjectPaths("PDB", out projectPath, out outputPath);
            string serverProjectPath = CodeGenHelper.ServerClassLibProjectPath(projectPath);
            string clientProjectPath = CodeGenHelper.ClientClassLibProjectPath(projectPath);
            ConsoleLogger logger = new ConsoleLogger();
            FilenameMap filenameMap = new FilenameMap();
            using (SourceFileLocationService locationService = new SourceFileLocationService(new[] { new PdbSourceFileProviderFactory(/*symbolSearchPath*/ null,logger) }, filenameMap))
            {
                List<string> files = new List<string>(locationService.GetFilesForType(typeof(TestEntity)));
                Assert.AreEqual(4, files.Count);

                CodeGenHelper.AssertContainsFiles(files, serverProjectPath, new string[] { "TestEntity.cs", "TestEntity.shared.cs", "TestEntity.linked.cs" });
                CodeGenHelper.AssertContainsFiles(files, clientProjectPath, new string[] { "TestEntity.reverse.linked.cs" });
            }
        }
Esempio n. 11
0
        /// <summary>
        /// Initializes a new instance of the <see cref="SharedSourceFiles"/> class.
        /// </summary>
        /// <param name="sourceFileLocationService">Service to use to locate source files for types or methods.
        /// It cannot be null.</param>
        /// <param name="filenameMap">Cache to map file names to an internal ID and back.</param>
        /// <param name="sharedFiles">The set of files to consider "shared" in answering requests about types or methods.
        /// It may be empty but it cannot be null.</param>
        internal SharedSourceFiles(ISourceFileLocationService sourceFileLocationService, FilenameMap filenameMap, IEnumerable <string> sharedFiles)
        {
            System.Diagnostics.Debug.Assert(sourceFileLocationService != null, "sourceFileLocationService cannot be null");
            System.Diagnostics.Debug.Assert(filenameMap != null, "filenameMap cannot be null");
            System.Diagnostics.Debug.Assert(sharedFiles != null, "sharedFiles cannot be null");

            this._sourceFileLocationService = sourceFileLocationService;
            this._filenameMap    = filenameMap;
            this._anySharedFiles = sharedFiles.Any();

            // Don't allocate anything if the list of files is empty
            if (this._anySharedFiles)
            {
                // Get a unique ID for every file declared as shared, and
                // keep this in a hashset for fast lookup
                foreach (string sharedFile in sharedFiles)
                {
                    this._sharedFileIds.Add(this._filenameMap.AddOrGet(sharedFile));
                }
            }
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="SharedSourceFiles"/> class.
        /// </summary>
        /// <param name="sourceFileLocationService">Service to use to locate source files for types or methods.  
        /// It cannot be null.</param>
        /// <param name="filenameMap">Cache to map file names to an internal ID and back.</param>
        /// <param name="sharedFiles">The set of files to consider "shared" in answering requests about types or methods.  
        /// It may be empty but it cannot be null.</param>
        internal SharedSourceFiles(ISourceFileLocationService sourceFileLocationService, FilenameMap filenameMap, IEnumerable<string> sharedFiles)
        {
            System.Diagnostics.Debug.Assert(sourceFileLocationService != null, "sourceFileLocationService cannot be null");
            System.Diagnostics.Debug.Assert(filenameMap != null, "filenameMap cannot be null");
            System.Diagnostics.Debug.Assert(sharedFiles != null, "sharedFiles cannot be null");

            this._sourceFileLocationService = sourceFileLocationService;
            this._filenameMap = filenameMap;
            this._anySharedFiles = sharedFiles.Any();

            // Don't allocate anything if the list of files is empty
            if (this._anySharedFiles)
            {
                // Get a unique ID for every file declared as shared, and
                // keep this in a hashset for fast lookup
                foreach (string sharedFile in sharedFiles)
                {
                    this._sharedFileIds.Add(this._filenameMap.AddOrGet(sharedFile));
                }
            }
        }
        public void SourceInfoAttribute_LocationService()
        {
            FilenameMap filenameMap = new FilenameMap();

            using (SourceFileLocationService locationService = new SourceFileLocationService(new[] { new SourceInfoSourceFileProviderFactory() }, filenameMap))
            {
                IEnumerable<string> files = locationService.GetFilesForType(typeof(SourceInfoDerivedTestClass));
                Assert.IsNotNull(files, "SourceInfoSourceFileLocator returned null");

                string[] expectedFiles = new string[] {
                    // "ctorLevel",    The base class ctor will not be exposed in the GetConstructors call 
                    "ctorLevelFileDerived",     // only the derived ctor will be found for this type
                    "propertyLevelFile",        // demonstrates we find properties in the base class
                    "propertyLevelFileDerived", //   and in the derived class
                    "methodLevelFile",          // demonstrates same for methods
                    "methodLevelFileDerived"
                };

                foreach (string file in expectedFiles)
                {
                    Assert.IsTrue(files.Contains(file), "Did not find expected file '" + file + "' using SourceInfoSourceFileLocator");
                }
            }
        }
 public void Dispose()
 {
     if (this._locationService != null)
     {
         this._locationService.Dispose();
         this._locationService = null;
     }
     this._filenameMap = null;
 }