public DocumentSnapshot(
     string path,
     long textVersion,
     Microsoft.CodeAnalysis.VersionStamp stamp,
     SourceText text)
 {
     Path            = path;
     TextVersion     = textVersion;
     _text           = text;
     DocumentVersion = stamp;
 }
 public DocumentSnapshot(
     string path,
     long textVersion,
     Microsoft.CodeAnalysis.VersionStamp stamp,
     TextLoader loader)
 {
     Path            = path;
     TextVersion     = textVersion;
     DocumentVersion = stamp;
     _loader         = loader;
 }
예제 #3
0
 /// <summary>
 /// Gets the version of the document's top level signature if it is already loaded and available.
 /// </summary>
 internal bool TryGetTopLevelChangeTextVersion(out VersionStamp version) =>
 DocumentState.TryGetTopLevelChangeTextVersion(out version);
예제 #4
0
 public ProjectInfo WithVersion(VersionStamp version)
 {
     return(With(attributes: Attributes.With(version: version)));
 }
예제 #5
0
 /// <summary>
 /// Create a new empty solution instance associated with this workspace.
 /// </summary>
 protected internal Solution CreateSolution(SolutionId id)
 {
     return(CreateSolution(SolutionInfo.Create(id, VersionStamp.Create())));
 }
예제 #6
0
 /// <summary>
 /// Gets the version of the document's top level signature if it is already loaded and available.
 /// </summary>
 internal bool TryGetTopLevelChangeTextVersion(out VersionStamp version)
 {
     return(_state.TryGetTopLevelChangeTextVersion(out version));
 }
예제 #7
0
        internal static bool TryGetReference(
            SolutionState solution, ProjectReference projectReference, Compilation finalOrDeclarationCompilation, VersionStamp version, out MetadataReference reference)
        {
            // if we have one from snapshot cache, use it. it will make sure same compilation will get same metadata reference always.
            MetadataOnlyReferenceSet referenceSet;

            if (s_snapshotCache.TryGetValue(finalOrDeclarationCompilation, out referenceSet))
            {
                solution.Workspace.LogTestMessage($"Found already cached metadata in {nameof(s_snapshotCache)} for the exact compilation");
                reference = referenceSet.GetMetadataReference(finalOrDeclarationCompilation, projectReference.Aliases, projectReference.EmbedInteropTypes);
                return(true);
            }

            // okay, now use version based cache that can live multiple compilation as long as there is no semantic changes.

            // get one for the branch
            if (TryGetReferenceFromBranch(solution.BranchId, projectReference, finalOrDeclarationCompilation, version, out reference))
            {
                solution.Workspace.LogTestMessage($"Found already cached metadata for the branch and version {version}");
                return(true);
            }

            // see whether we can use primary branch one
            var primaryBranchId = solution.Workspace.PrimaryBranchId;

            if (solution.BranchId != primaryBranchId &&
                TryGetReferenceFromBranch(primaryBranchId, projectReference, finalOrDeclarationCompilation, version, out reference))
            {
                solution.Workspace.LogTestMessage($"Found already cached metadata for the primary branch and version {version}");
                return(true);
            }

            // noop, we don't have any
            reference = null;
            return(false);
        }
예제 #8
0
 public MetadataOnlyReferenceSet(VersionStamp version, MetadataOnlyImage image)
 {
     _version = version;
     _image   = image;
 }
예제 #9
0
 public bool TryGetTextVersion(out VersionStamp version)
 {
     version = _version;
     return(version != default(VersionStamp));
 }
예제 #10
0
 public TreeTextSource(ValueSource <SourceText> text, VersionStamp version, string filePath)
 {
     _lazyText = text;
     _version  = version;
     _filePath = filePath;
 }
예제 #11
0
        /// <summary>
        /// Adds a document to the workspace.
        /// </summary>
        public DocumentId AddDocument(ProjectId projectId, string name, string text)
        {
            if (projectId == null)
            {
                throw new ArgumentNullException("projectId");
            }

            if (name == null)
            {
                throw new ArgumentNullException("name");
            }

            if (text == null)
            {
                throw new ArgumentNullException("text");
            }

            var id = DocumentId.CreateNewId(projectId);

            this.AddDocument(
                DocumentInfo.Create(id, name, loader: TextLoader.From(TextAndVersion.Create(SourceText.From(text), VersionStamp.Create()))));

            return(id);
        }
예제 #12
0
 internal SolutionInfo WithVersion(VersionStamp version)
 {
     return(With(attributes: new SolutionAttributes(Attributes.Id, version, Attributes.FilePath)));
 }
예제 #13
0
 public SolutionAttributes(SolutionId id, VersionStamp version, string filePath)
 {
     Id       = id ?? throw new ArgumentNullException(nameof(id));
     Version  = version;
     FilePath = filePath;
 }
예제 #14
0
 public SolutionAttributes WithVersion(VersionStamp versionStamp)
 {
     return(new SolutionAttributes(Id, versionStamp, FilePath));
 }
예제 #15
0
 /// <summary>
 /// Creates a new solution instance that includes a project with the specified language and names.
 /// </summary>
 public Solution AddProject(ProjectId projectId, string name, string assemblyName, string language)
 {
     return(this.AddProject(ProjectInfo.Create(projectId, VersionStamp.Create(), name, assemblyName, language)));
 }
예제 #16
0
        private static TreeAndVersion MakeNewTreeAndVersion(SyntaxTree oldTree, SourceText oldText, VersionStamp oldVersion, SyntaxTree newTree, SourceText newText, VersionStamp newVersion)
        {
            var topLevelChanged = TopLevelChanged(oldTree, oldText, newTree, newText);
            var version         = topLevelChanged ? newVersion : oldVersion;

            return(TreeAndVersion.Create(newTree, version));
        }
예제 #17
0
        private static bool TryGetReferenceFromBranch(
            BranchId branchId, ProjectReference projectReference, Compilation finalOrDeclarationCompilation, VersionStamp version, out MetadataReference reference)
        {
            // get map for the branch
            var mapFromBranch = s_cache.GetValue(branchId, s_createReferenceSetMap);

            // if we have one, return it
            MetadataOnlyReferenceSet referenceSet;

            if (mapFromBranch.TryGetValue(projectReference.ProjectId, out referenceSet) &&
                (version == VersionStamp.Default || referenceSet.Version == version))
            {
                // record it to snapshot based cache.
                var newReferenceSet = s_snapshotCache.GetValue(finalOrDeclarationCompilation, _ => referenceSet);

                reference = newReferenceSet.GetMetadataReference(finalOrDeclarationCompilation, projectReference.Aliases, projectReference.EmbedInteropTypes);
                return(true);
            }

            reference = null;
            return(false);
        }
예제 #18
0
 public ProjectInfo WithVersion(VersionStamp version)
 {
     return(this.With(version: version));
 }
예제 #19
0
        internal static MetadataReference GetOrBuildReference(
            SolutionState solution,
            ProjectReference projectReference,
            Compilation finalCompilation,
            VersionStamp version,
            CancellationToken cancellationToken)
        {
            solution.Workspace.LogTestMessage($"Looking to see if we already have a skeleton assembly for {projectReference.ProjectId} before we build one...");
            MetadataReference reference;

            if (TryGetReference(solution, projectReference, finalCompilation, version, out reference))
            {
                solution.Workspace.LogTestMessage($"A reference was found {projectReference.ProjectId} so we're skipping the build.");
                return(reference);
            }

            // okay, we don't have one. so create one now.

            // first, prepare image
            // * NOTE * image is cancellable, do not create it inside of conditional weak table.
            var service = solution.Workspace.Services.GetService <ITemporaryStorageService>();
            var image   = MetadataOnlyImage.Create(solution.Workspace, service, finalCompilation, cancellationToken);

            if (image.IsEmpty)
            {
                // unfortunately, we couldn't create one. do best effort
                if (TryGetReference(solution, projectReference, finalCompilation, VersionStamp.Default, out reference))
                {
                    solution.Workspace.LogTestMessage($"We failed to create metadata so we're using the one we just found from an earlier version.");

                    // we have one from previous compilation!!, it might be out-of-date big time, but better than nothing.
                    // re-use it
                    return(reference);
                }
            }

            // okay, proceed with whatever image we have

            // now, remove existing set
            var mapFromBranch = s_cache.GetValue(solution.BranchId, s_createReferenceSetMap);

            mapFromBranch.Remove(projectReference.ProjectId);

            // create new one
            var newReferenceSet = new MetadataOnlyReferenceSet(version, image);
            var referenceSet    = s_snapshotCache.GetValue(finalCompilation, _ => newReferenceSet);

            if (newReferenceSet != referenceSet)
            {
                // someone else has beaten us.
                // let image go eagerly. otherwise, finalizer in temporary storage will take care of it
                image.Cleanup();

                // return new reference
                return(referenceSet.GetMetadataReference(finalCompilation, projectReference.Aliases, projectReference.EmbedInteropTypes));
            }
            else
            {
                solution.Workspace.LogTestMessage($"Successfully stored the metadata generated for {projectReference.ProjectId}");
            }

            // record it to version based cache as well. snapshot cache always has a higher priority. we don't need to check returned set here
            // since snapshot based cache will take care of same compilation for us.
            mapFromBranch.GetValue(projectReference.ProjectId, _ => referenceSet);

            // return new reference
            return(referenceSet.GetMetadataReference(finalCompilation, projectReference.Aliases, projectReference.EmbedInteropTypes));
        }
예제 #20
0
파일: TextLoader.cs 프로젝트: khm1600/CJing
 internal TextContainerLoader(SourceTextContainer container, VersionStamp version, string filePath)
 {
     _container = container;
     _version   = version;
     _filePath  = filePath;
 }
예제 #21
0
        /// <summary>
        /// Create a <see cref="ProjectInfo"/> structure initialized from a compilers command line arguments.
        /// </summary>
        public static ProjectInfo CreateProjectInfo(string projectName, string language, IEnumerable <string> commandLineArgs, string projectDirectory, Workspace workspace = null)
        {
            // TODO (tomat): the method may throw all sorts of exceptions.
            var tmpWorkspace     = workspace ?? new AdhocWorkspace(DesktopMefHostServices.DefaultServices);
            var languageServices = tmpWorkspace.Services.GetLanguageServices(language);

            if (languageServices == null)
            {
                throw new ArgumentException(WorkspacesResources.Unrecognized_language_name);
            }

            var commandLineParser    = languageServices.GetRequiredService <ICommandLineParserService>();
            var commandLineArguments = commandLineParser.Parse(commandLineArgs, projectDirectory, isInteractive: false, sdkDirectory: RuntimeEnvironment.GetRuntimeDirectory());

            var metadataService = tmpWorkspace.Services.GetRequiredService <IMetadataService>();

            // we only support file paths in /r command line arguments
            var relativePathResolver =
                new RelativePathResolver(commandLineArguments.ReferencePaths, commandLineArguments.BaseDirectory);
            var commandLineMetadataReferenceResolver = new WorkspaceMetadataFileReferenceResolver(
                metadataService, relativePathResolver);

            var analyzerLoader     = tmpWorkspace.Services.GetRequiredService <IAnalyzerService>().GetLoader();
            var xmlFileResolver    = new XmlFileResolver(commandLineArguments.BaseDirectory);
            var strongNameProvider = new DesktopStrongNameProvider(commandLineArguments.KeyFileSearchPaths);

            // resolve all metadata references.
            var boundMetadataReferences      = commandLineArguments.ResolveMetadataReferences(commandLineMetadataReferenceResolver);
            var unresolvedMetadataReferences = boundMetadataReferences.FirstOrDefault(r => r is UnresolvedMetadataReference);

            if (unresolvedMetadataReferences != null)
            {
                throw new ArgumentException(string.Format(WorkspacesResources.Can_t_resolve_metadata_reference_colon_0, ((UnresolvedMetadataReference)unresolvedMetadataReferences).Reference));
            }

            // resolve all analyzer references.
            foreach (var path in commandLineArguments.AnalyzerReferences.Select(r => r.FilePath))
            {
                analyzerLoader.AddDependencyLocation(relativePathResolver.ResolvePath(path, baseFilePath: null));
            }

            var boundAnalyzerReferences      = commandLineArguments.ResolveAnalyzerReferences(analyzerLoader);
            var unresolvedAnalyzerReferences = boundAnalyzerReferences.FirstOrDefault(r => r is UnresolvedAnalyzerReference);

            if (unresolvedAnalyzerReferences != null)
            {
                throw new ArgumentException(string.Format(WorkspacesResources.Can_t_resolve_analyzer_reference_colon_0, ((UnresolvedAnalyzerReference)unresolvedAnalyzerReferences).Display));
            }

            AssemblyIdentityComparer assemblyIdentityComparer;

            if (commandLineArguments.AppConfigPath != null)
            {
                try
                {
                    using var appConfigStream = new FileStream(commandLineArguments.AppConfigPath, FileMode.Open, FileAccess.Read);

                    assemblyIdentityComparer = DesktopAssemblyIdentityComparer.LoadFromXml(appConfigStream);
                }
                catch (Exception e)
                {
                    throw new ArgumentException(string.Format(WorkspacesResources.An_error_occurred_while_reading_the_specified_configuration_file_colon_0, e.Message));
                }
            }
            else
            {
                assemblyIdentityComparer = DesktopAssemblyIdentityComparer.Default;
            }

            var projectId = ProjectId.CreateNewId(debugName: projectName);

            // construct file infos
            var docs = new List <DocumentInfo>();

            foreach (var fileArg in commandLineArguments.SourceFiles)
            {
                var absolutePath = Path.IsPathRooted(fileArg.Path) || string.IsNullOrEmpty(projectDirectory)
                    ? Path.GetFullPath(fileArg.Path)
                    : Path.GetFullPath(Path.Combine(projectDirectory, fileArg.Path));

                var relativePath    = PathUtilities.GetRelativePath(projectDirectory, absolutePath);
                var isWithinProject = PathUtilities.IsChildPath(projectDirectory, absolutePath);

                var folderRoot = isWithinProject ? Path.GetDirectoryName(relativePath) : "";
                var folders    = isWithinProject ? GetFolders(relativePath) : null;
                var name       = Path.GetFileName(relativePath);
                var id         = DocumentId.CreateNewId(projectId, absolutePath);

                var doc = DocumentInfo.Create(
                    id: id,
                    name: name,
                    folders: folders,
                    sourceCodeKind: fileArg.IsScript ? SourceCodeKind.Script : SourceCodeKind.Regular,
                    loader: new FileTextLoader(absolutePath, commandLineArguments.Encoding),
                    filePath: absolutePath);

                docs.Add(doc);
            }

            // construct file infos for additional files.
            var additionalDocs = new List <DocumentInfo>();

            foreach (var fileArg in commandLineArguments.AdditionalFiles)
            {
                var absolutePath = Path.IsPathRooted(fileArg.Path) || string.IsNullOrEmpty(projectDirectory)
                        ? Path.GetFullPath(fileArg.Path)
                        : Path.GetFullPath(Path.Combine(projectDirectory, fileArg.Path));

                var relativePath    = PathUtilities.GetRelativePath(projectDirectory, absolutePath);
                var isWithinProject = PathUtilities.IsChildPath(projectDirectory, absolutePath);

                var folderRoot = isWithinProject ? Path.GetDirectoryName(relativePath) : "";
                var folders    = isWithinProject ? GetFolders(relativePath) : null;
                var name       = Path.GetFileName(relativePath);
                var id         = DocumentId.CreateNewId(projectId, absolutePath);

                var doc = DocumentInfo.Create(
                    id: id,
                    name: name,
                    folders: folders,
                    sourceCodeKind: SourceCodeKind.Regular,
                    loader: new FileTextLoader(absolutePath, commandLineArguments.Encoding),
                    filePath: absolutePath);

                additionalDocs.Add(doc);
            }

            // If /out is not specified and the project is a console app the csc.exe finds out the Main method
            // and names the compilation after the file that contains it. We don't want to create a compilation,
            // bind Mains etc. here. Besides the msbuild always includes /out in the command line it produces.
            // So if we don't have the /out argument we name the compilation "<anonymous>".
            string assemblyName = (commandLineArguments.OutputFileName != null) ?
                                  Path.GetFileNameWithoutExtension(commandLineArguments.OutputFileName) : "<anonymous>";

            // TODO (tomat): what should be the assemblyName when compiling a netmodule? Should it be /moduleassemblyname

            var projectInfo = ProjectInfo.Create(
                projectId,
                VersionStamp.Create(),
                projectName,
                assemblyName,
                language: language,
                compilationOptions: commandLineArguments.CompilationOptions
                .WithXmlReferenceResolver(xmlFileResolver)
                .WithAssemblyIdentityComparer(assemblyIdentityComparer)
                .WithStrongNameProvider(strongNameProvider)
                // TODO (https://github.com/dotnet/roslyn/issues/4967):
                .WithMetadataReferenceResolver(new WorkspaceMetadataFileReferenceResolver(metadataService, new RelativePathResolver(ImmutableArray <string> .Empty, projectDirectory))),
                parseOptions: commandLineArguments.ParseOptions,
                documents: docs,
                additionalDocuments: additionalDocs,
                metadataReferences: boundMetadataReferences,
                analyzerReferences: boundAnalyzerReferences);

            return(projectInfo);
        }
예제 #22
0
 private static TextAndVersion GetProperTextAndVersion(SourceText oldText, SourceText newText, VersionStamp version, string filePath)
 {
     // if the supplied text is the same as the previous text, then also use same version
     // otherwise use new version
     return oldText.ContentEquals(newText)
         ? TextAndVersion.Create(newText, version, filePath)
         : TextAndVersion.Create(newText, version.GetNewerVersion(), filePath);
 }
예제 #23
0
        private static async Task <VersionStamp> ComputeTopLevelChangeTextVersionAsync(VersionStamp oldVersion, TextDocumentState newDocument, CancellationToken cancellationToken)
        {
            var newVersion = await newDocument.GetTopLevelChangeTextVersionAsync(cancellationToken).ConfigureAwait(false);

            return(newVersion.GetNewerVersion(oldVersion));
        }
예제 #24
0
 /// <summary>
 /// Gets the version of the document's text if it is already loaded and available.
 /// </summary>
 public bool TryGetTextVersion(out VersionStamp version)
 {
     return(this.state.TryGetTextVersion(out version));
 }
예제 #25
0
 private TreeAndVersion(SyntaxTree tree, VersionStamp version)
 {
     this.Tree    = tree;
     this.Version = version;
 }
예제 #26
0
 /// <summary>
 /// Gets the version of the document's text if it is already loaded and available.
 /// </summary>
 public bool TryGetTextVersion(out VersionStamp version)
 {
     return(this.GetDocumentState().TryGetTextVersion(out version));
 }