public AddAdditionalDocumentUndoUnit( VisualStudioWorkspaceImpl workspace, DocumentInfo docInfo, SourceText text) : base(workspace, docInfo, text) { }
public static DocumentState Create( DocumentInfo info, ParseOptions options, HostLanguageServices language, SolutionServices services) { var textSource = info.TextLoader != null ? CreateRecoverableText(info.TextLoader, info.Id, services) : CreateStrongText(TextAndVersion.Create(SourceText.From(string.Empty, Encoding.UTF8), VersionStamp.Default, info.FilePath)); var treeSource = CreateLazyFullyParsedTree( textSource, GetSyntaxTreeFilePath(info), options, languageServices: language); // remove any initial loader so we don't keep source alive info = info.WithTextLoader(null); return new DocumentState( languageServices: language, solutionServices: services, info: info, options: options, textSource: textSource, treeSource: treeSource); }
protected TextDocumentState( SolutionServices solutionServices, DocumentInfo info, ValueSource<TextAndVersion> textSource) { this.solutionServices = solutionServices; this.info = info; this.textSource = textSource; }
protected AbstractAddDocumentUndoUnit( VisualStudioWorkspaceImpl workspace, DocumentInfo docInfo, SourceText text) : base(workspace, docInfo.Id.ProjectId) { DocumentInfo = docInfo; Text = text; }
private DocumentState( HostLanguageServices languageServices, SolutionServices solutionServices, DocumentInfo info, ParseOptions options, ValueSource<TextAndVersion> textSource, ValueSource<TreeAndVersion> treeSource) : base(solutionServices, info, textSource) { _languageServices = languageServices; _options = options; _treeSource = treeSource; }
public static TextDocumentState Create(DocumentInfo info, SolutionServices services) { var textSource = info.TextLoader != null ? CreateRecoverableText(info.TextLoader, info.Id, services, reportInvalidDataException: false) : CreateStrongText(TextAndVersion.Create(SourceText.From(string.Empty, Encoding.UTF8), VersionStamp.Default, info.FilePath)); // remove any initial loader so we don't keep source alive info = info.WithTextLoader(null); return new TextDocumentState( solutionServices: services, info: info, textSource: textSource); }
private DocumentState( HostLanguageServices languageServices, SolutionServices solutionServices, DocumentInfo info, ParseOptions options, ValueSource<TextAndVersion> textSource, ValueSource<TreeAndVersion> treeSource) { this.languageServices = languageServices; this.solutionServices = solutionServices; this.info = info; this.options = options; this.textSource = textSource; this.treeSource = treeSource; }
private void CreateSimpleWorkspace(out OmnisharpWorkspace workspace, out ChangeBufferService controller, out DocumentInfo document, string filename, string contents) { workspace = new OmnisharpWorkspace(new HostServicesBuilder(Enumerable.Empty<ICodeActionProvider>())); controller = new ChangeBufferService(workspace); var projectInfo = ProjectInfo.Create(ProjectId.CreateNewId(), VersionStamp.Create(), "ProjectNameVal", "AssemblyNameVal", LanguageNames.CSharp); document = DocumentInfo.Create(DocumentId.CreateNewId(projectInfo.Id), filename, null, SourceCodeKind.Regular, TextLoader.From(TextAndVersion.Create(SourceText.From(contents), VersionStamp.Create())), filename); workspace.AddProject(projectInfo); workspace.AddDocument(document); }
private void CreateSimpleWorkspace(out OmnisharpWorkspace workspace, out OmnisharpController controller, out DocumentInfo document, string filename, string contents) { workspace = new OmnisharpWorkspace(); controller = new OmnisharpController(workspace, null); var projectInfo = ProjectInfo.Create(ProjectId.CreateNewId(), VersionStamp.Create(), "ProjectNameVal", "AssemblyNameVal", LanguageNames.CSharp); document = DocumentInfo.Create(DocumentId.CreateNewId(projectInfo.Id), filename, null, SourceCodeKind.Regular, TextLoader.From(TextAndVersion.Create(SourceText.From(contents), VersionStamp.Create())), filename); workspace.AddProject(projectInfo); workspace.AddDocument(document); }
protected TextDocumentState( SolutionServices solutionServices, DocumentInfo info, SourceText sourceTextOpt, ValueSource<TextAndVersion> textAndVersionSource, ValueSource<DocumentStateChecksums> lazyChecksums) { this.solutionServices = solutionServices; this.info = info; this.sourceTextOpt = sourceTextOpt; this.textAndVersionSource = textAndVersionSource; // for now, let it re-calculate if anything changed. // TODO: optimize this so that we only re-calcuate checksums that are actually changed _lazyChecksums = new AsyncLazy<DocumentStateChecksums>(ComputeChecksumsAsync, cacheResult: true); }
private DocumentState( HostLanguageServices languageServices, SolutionServices solutionServices, DocumentInfo info, ParseOptions options, ValueSource<TextAndVersion> textSource, ValueSource<TreeAndVersion> treeSource) : base(solutionServices, info, textSource) { _languageServices = languageServices; _options = options; // If this is document that doesn't support syntax, then don't even bother holding // onto any tree source. It will never be used to get a tree, and can only hurt us // by possibly holding onto data that might cause a slow memory leak. _treeSource = this.SupportsSyntaxTree ? treeSource : ValueSource<TreeAndVersion>.Empty; }
public Solution AddAdditionalDocument(DocumentInfo documentInfo) { return(AddAdditionalDocuments(ImmutableArray.Create(documentInfo))); }
/// <summary> /// Create a <see cref="ProjectInfo"/> structure initialized from a compilers command line arguments. /// </summary> public static ProjectInfo CreateProjectInfo(Workspace workspace, string projectName, string language, IEnumerable <string> commandLineArgs, string projectDirectory) { // TODO (tomat): the method may throw all sorts of exceptions. var languageServices = workspace.Services.GetLanguageServices(language); if (languageServices == null) { throw new ArgumentException(WorkspacesResources.UnrecognizedLanguageName); } var commandLineArgumentsFactory = languageServices.GetService <ICommandLineArgumentsFactoryService>(); var commandLineArguments = commandLineArgumentsFactory.CreateCommandLineArguments(commandLineArgs, projectDirectory, isInteractive: false); // TODO (tomat): to match csc.exe/vbc.exe we should use CommonCommandLineCompiler.ExistingReferencesResolver to deal with #r's var referenceResolver = new MetadataFileReferenceResolver(commandLineArguments.ReferencePaths, commandLineArguments.BaseDirectory); var referenceProvider = workspace.Services.GetService <IMetadataReferenceProviderService>().GetProvider(); var xmlFileResolver = new XmlFileResolver(commandLineArguments.BaseDirectory); var strongNameProvider = new DesktopStrongNameProvider(commandLineArguments.KeyFileSearchPaths); // resolve all metadata references. var boundMetadataReferences = commandLineArguments.ResolveMetadataReferences(referenceResolver, referenceProvider); var unresolvedMetadataReferences = boundMetadataReferences.FirstOrDefault(r => r is UnresolvedMetadataReference); if (unresolvedMetadataReferences != null) { throw new ArgumentException(string.Format(WorkspacesResources.CantResolveMetadataReference, ((UnresolvedMetadataReference)unresolvedMetadataReferences).Reference)); } // resolve all analyzer references. var boundAnalyzerReferences = commandLineArguments.ResolveAnalyzerReferences(); var unresolvedAnalyzerReferences = boundAnalyzerReferences.FirstOrDefault(r => r is UnresolvedAnalyzerReference); if (unresolvedAnalyzerReferences != null) { throw new ArgumentException(string.Format(WorkspacesResources.CantResolveAnalyzerReference, ((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.ErrorWhileReadingSpecifiedConfigFile, 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 = FilePathUtilities.GetRelativePath(projectDirectory, absolutePath); var isWithinProject = !Path.IsPathRooted(relativePath); 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.AdditionalStreams) { var absolutePath = Path.IsPathRooted(fileArg.Path) || string.IsNullOrEmpty(projectDirectory) ? Path.GetFullPath(fileArg.Path) : Path.GetFullPath(Path.Combine(projectDirectory, fileArg.Path)); var relativePath = FilePathUtilities.GetRelativePath(projectDirectory, absolutePath); var isWithinProject = !Path.IsPathRooted(relativePath); 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) .WithMetadataReferenceResolver(referenceResolver) .WithMetadataReferenceProvider(referenceProvider), parseOptions: commandLineArguments.ParseOptions, documents: docs, additionalDocuments: additionalDocs, metadataReferences: boundMetadataReferences, analyzerReferences: boundAnalyzerReferences); return(projectInfo); }
public void AddDocument(DocumentInfo documentInfo) { OnDocumentAdded(documentInfo); }
/// <summary> /// Adds a document to the workspace. /// </summary> public void AddDocument(DocumentInfo documentInfo) { if (documentInfo == null) { throw new ArgumentNullException("documentInfo"); } this.OnDocumentAdded(documentInfo); }
protected override void ApplyDocumentAdded (DocumentInfo info, SourceText text) { var id = info.Id; MonoDevelop.Projects.Project mdProject = null; if (id.ProjectId != null) { var project = CurrentSolution.GetProject (id.ProjectId); mdProject = GetMonoProject (project); if (mdProject == null) LoggingService.LogWarning ("Couldn't find project for newly generated file {0} (Project {1}).", info.Name, info.Id.ProjectId); } var path = DetermineFilePath (info.Id, info.Name, info.FilePath, info.Folders, mdProject?.FileName.ParentDirectory, true); string formattedText; var formatter = CodeFormatterService.GetFormatter (DesktopService.GetMimeTypeForUri (path)); if (formatter != null && mdProject != null) { formattedText = formatter.FormatText (mdProject.Policies, text.ToString ()); } else { formattedText = text.ToString (); } var textSource = new StringTextSource (formattedText, text.Encoding ?? System.Text.Encoding.UTF8); try { textSource.WriteTextTo (path); } catch (Exception e) { LoggingService.LogError ("Exception while saving file to " + path, e); } if (mdProject != null) { var file = new MonoDevelop.Projects.ProjectFile (path); Application.Invoke (delegate { mdProject.Files.Add (file); IdeApp.ProjectOperations.SaveAsync (mdProject); }); } }
/// <summary> /// This method is called when a document is first observed. /// </summary> protected virtual void RegisterDocument(DocumentInfo documentInfo) { }
// This is the string used to represent the FilePath property on a SyntaxTree object. // if the document does not yet have a file path, use the document's name instead in regular code // or an empty string in script code. private static string GetSyntaxTreeFilePath(DocumentInfo info) { if (info.FilePath != null) { return info.FilePath; } return info.SourceCodeKind == SourceCodeKind.Regular ? info.Name : ""; }
public void OnAdditionalDocumentAdded(DocumentInfo documentInfo) { }
// use static method so we don't capture references to this private static Tuple<AsyncLazy<TextAndVersion>, TreeAndVersion> CreateRecoverableTextAndTree( SyntaxNode newRoot, VersionStamp textVersion, VersionStamp treeVersion, DocumentInfo info, ParseOptions options, ISyntaxTreeFactoryService factory, PreservationMode mode, SolutionServices solutionServices) { string filePath = info.FilePath; TreeAndVersion lazyTree = null; // Since this text will be created from a tree, it doesn't have an explicit encoding. // We'll check for this case when writing out the file, and look at the original file's // encoding. Encoding encoding = null; // this captures the lazyTree local var lazyText = new AsyncLazy<TextAndVersion>( c => GetTextAndVersionAsync(lazyTree, textVersion, encoding, filePath, c), c => GetTextAndVersion(lazyTree, textVersion, encoding, filePath, c), cacheResult: false); lazyTree = TreeAndVersion.Create( (mode == PreservationMode.PreserveIdentity) || !solutionServices.SupportsCachingRecoverableObjects ? factory.CreateSyntaxTree(GetSyntaxTreeFilePath(info), options, newRoot, encoding) : factory.CreateRecoverableTree(info.Id.ProjectId, GetSyntaxTreeFilePath(info), options, lazyText, newRoot), treeVersion); return Tuple.Create(lazyText, lazyTree); }
/// <summary> /// Create a new solution instance with the corresponding project updated to include a new /// document instanced defined by the document info. /// </summary> public Solution AddDocument(DocumentInfo documentInfo) { if (documentInfo == null) { throw new ArgumentNullException(nameof(documentInfo)); } CheckContainsProject(documentInfo.Id.ProjectId); CheckNotContainsDocument(documentInfo.Id); var project = this.GetProjectState(documentInfo.Id.ProjectId); var doc = DocumentState.Create( documentInfo, project.ParseOptions, project.LanguageServices, _solutionServices).UpdateSourceCodeKind(documentInfo.SourceCodeKind); return this.AddDocument(doc); }
/// <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); }
// use static method so we don't capture references to this private static Tuple<ValueSource<TextAndVersion>, TreeAndVersion> CreateRecoverableTextAndTree( SyntaxNode newRoot, VersionStamp textVersion, VersionStamp treeVersion, Encoding encoding, DocumentInfo info, ParseOptions options, ISyntaxTreeFactoryService factory, PreservationMode mode, SolutionServices solutionServices) { string filePath = info.FilePath; SyntaxTree tree = null; ValueSource<TextAndVersion> lazyTextAndVersion = null; if ((mode == PreservationMode.PreserveIdentity) || !factory.CanCreateRecoverableTree(newRoot)) { // its okay to use a strong cached AsyncLazy here because the compiler layer SyntaxTree will also keep the text alive once its built. lazyTextAndVersion = new TreeTextSource( new AsyncLazy<SourceText>( c => tree.GetTextAsync(c), c => tree.GetText(c), cacheResult: true), textVersion, filePath); tree = factory.CreateSyntaxTree(GetSyntaxTreeFilePath(info), options, encoding, newRoot); } else { // uses CachedWeakValueSource so the document and tree will return the same SourceText instance across multiple accesses as long // as the text is referenced elsewhere. lazyTextAndVersion = new TreeTextSource( new CachedWeakValueSource<SourceText>( new AsyncLazy<SourceText>( c => BuildRecoverableTreeTextAsync(tree, encoding, c), c => BuildRecoverableTreeText(tree, encoding, c), cacheResult: false)), textVersion, filePath); tree = factory.CreateRecoverableTree(info.Id.ProjectId, GetSyntaxTreeFilePath(info), options, lazyTextAndVersion, encoding, newRoot); } return Tuple.Create(lazyTextAndVersion, TreeAndVersion.Create(tree, treeVersion)); }
public void OnDocumentAdded(DocumentInfo documentInfo) { }
/// <summary> /// Adds a document to the workspace. /// </summary> public Document AddDocument(DocumentInfo documentInfo) { if (documentInfo == null) { throw new ArgumentNullException(nameof(documentInfo)); } this.OnDocumentAdded(documentInfo); return this.CurrentSolution.GetDocument(documentInfo.Id); }
public SolutionState AddAdditionalDocument(DocumentInfo documentInfo) { if (documentInfo == null) { throw new ArgumentNullException(nameof(documentInfo)); } CheckContainsProject(documentInfo.Id.ProjectId); CheckNotContainsAdditionalDocument(documentInfo.Id); var oldProject = this.GetProjectState(documentInfo.Id.ProjectId); var state = TextDocumentState.Create( documentInfo, _solutionServices); var newProject = oldProject.AddAdditionalDocument(state); return this.ForkProject(newProject); }
protected override void ApplyDocumentAdded(DocumentInfo info, SourceText text) { System.Diagnostics.Debug.Assert(_applyChangesProjectFile != null); var project = this.CurrentSolution.GetProject(info.Id.ProjectId); IProjectFileLoader loader; if (this.TryGetLoaderFromProjectPath(project.FilePath, ReportMode.Ignore, out loader)) { var extension = _applyChangesProjectFile.GetDocumentExtension(info.SourceCodeKind); var fileName = Path.ChangeExtension(info.Name, extension); var relativePath = (info.Folders != null && info.Folders.Count > 0) ? Path.Combine(Path.Combine(info.Folders.ToArray()), fileName) : fileName; var fullPath = GetAbsolutePath(relativePath, Path.GetDirectoryName(project.FilePath)); var newDocumentInfo = info.WithName(fileName) .WithFilePath(fullPath) .WithTextLoader(new FileTextLoader(fullPath, text.Encoding)); // add document to project file _applyChangesProjectFile.AddDocument(relativePath); // add to solution this.OnDocumentAdded(newDocumentInfo); // save text to disk if (text != null) { this.SaveDocumentText(info.Id, fullPath, text, text.Encoding ?? Encoding.UTF8); } } }
public Solution AddAdditionalDocument(DocumentInfo documentInfo) { var newState = _state.AddAdditionalDocument(documentInfo); if (newState == _state) { return this; } return new Solution(newState); }
public Solution AddAdditionalDocument(DocumentInfo documentInfo) { if (documentInfo == null) { throw new ArgumentNullException(nameof(documentInfo)); } CheckContainsProject(documentInfo.Id.ProjectId); CheckNotContainsAdditionalDocument(documentInfo.Id); var project = this.GetProjectState(documentInfo.Id.ProjectId); var doc = TextDocumentState.Create( documentInfo, _solutionServices); return this.AddAdditionalDocument(doc); }
public static ProjectInfo CreateProjectInfo(string projectName, string language, IEnumerable <string> commandLineArgs, string projectDirectory, Workspace workspace = null) #pragma warning restore RS0026 // Type is forwarded from MS.CA.Workspaces.Desktop. { // TODO (tomat): the method may throw all sorts of exceptions. var tmpWorkspace = workspace ?? new AdhocWorkspace(); 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. // // In the command line compiler, it's entirely possible that duplicate reference paths may appear in this list; in the compiler // each MetadataReference object is a distinct instance, and the deduplication is ultimately performed in the ReferenceManager // once the Compilation actually starts to read metadata. In this code however, we're resolving with the IMetadataService, which // has a default implementation to cache and return the same MetadataReference instance for a duplicate. This means duplicate // reference path will create duplicate MetadataReference objects, which is disallowed by ProjectInfo.Create -- even though the // compiler eventually would have dealt with it just fine. It's reasonable the Workspace APIs disallow duplicate reference objects // since it makes the semantics of APIs like Add/RemoveMetadataReference tricky. But since we want to not break for command lines // with duplicate references, we'll do a .Distinct() here, and let the Compilation do any further deduplication // that isn't handled by this explicit instance check. This does mean that the Compilations produced through this API // won't produce the "duplicate metadata reference" diagnostic like the real command line compiler would, but that's probably fine. // // Alternately, we could change the IMetadataService behavior to simply not cache, but that could theoretically break other // callers that would now see references across projects not be the same, or hurt performance for users of MSBuildWorkspace. Given // this is an edge case, it's not worth the larger fix here. var boundMetadataReferences = commandLineArguments.ResolveMetadataReferences(commandLineMetadataReferenceResolver).Distinct().ToList(); 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>". var 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); }
/// <summary> /// Create a new solution instance with the corresponding project updated to include a new /// document instanced defined by the document info. /// </summary> public SolutionState AddDocument(DocumentInfo documentInfo) { if (documentInfo == null) { throw new ArgumentNullException(nameof(documentInfo)); } CheckContainsProject(documentInfo.Id.ProjectId); CheckNotContainsDocument(documentInfo.Id); var oldProject = this.GetProjectState(documentInfo.Id.ProjectId); var state = DocumentState.Create( documentInfo, oldProject.ParseOptions, oldProject.LanguageServices, _solutionServices).UpdateSourceCodeKind(documentInfo.SourceCodeKind); var newProject = oldProject.AddDocument(state); return this.ForkProject( newProject, CompilationTranslationAction.AddDocument(state), newLinkedFilesMap: CreateLinkedFilesMapWithAddedDocuments(newProject, SpecializedCollections.SingletonEnumerable(state.Id))); }
// use static method so we don't capture references to this private static Tuple<AsyncLazy<TextAndVersion>, AsyncLazy<TreeAndVersion>> CreateRecoverableTextAndTree( SyntaxNode newRoot, VersionStamp textVersion, VersionStamp treeVersion, DocumentInfo info, ParseOptions options, ISyntaxTreeFactoryService factory, PreservationMode mode) { string filePath = info.FilePath; Encoding encoding = info.DefaultEncoding; AsyncLazy<TreeAndVersion> lazyTree = null; // this captures the lazyTree local var lazyText = new AsyncLazy<TextAndVersion>( c => GetTextAndVersionAsync(lazyTree, textVersion, encoding, filePath, c), c => GetTextAndVersion(lazyTree, textVersion, encoding, filePath, c), cacheResult: false); // this should be only called when we do forking, since there is no cheap way to figure out what has been changed, // we will always consider top level being changed by giving new version here. if (mode == PreservationMode.PreserveIdentity) { lazyTree = new AsyncLazy<TreeAndVersion>( TreeAndVersion.Create(factory.CreateSyntaxTree(GetSyntaxTreeFilePath(info), options, newRoot, encoding), treeVersion)); } else { lazyTree = new AsyncLazy<TreeAndVersion>( TreeAndVersion.Create(factory.CreateRecoverableTree(GetSyntaxTreeFilePath(info), options, lazyText, newRoot, reparse: false), treeVersion)); } return Tuple.Create(lazyText, lazyTree); }
protected override void ApplyAdditionalDocumentAdded (DocumentInfo info, SourceText text) { base.ApplyAdditionalDocumentAdded (info, text); }
// This is the string used to represent the FilePath property on a SyntaxTree object. // if the document does not yet have a file path, use the document's name instead. private static string GetSyntaxTreeFilePath(DocumentInfo info) { return info.FilePath ?? info.Name; }
private static DocumentState CreateDocument(ProjectInfo projectInfo, DocumentInfo documentInfo, ILanguageServiceProvider languageServices, SolutionServices solutionServices) { var doc = DocumentState.Create(documentInfo, projectInfo.ParseOptions, languageServices, solutionServices); if (doc.SourceCodeKind != documentInfo.SourceCodeKind) { doc = doc.UpdateSourceCodeKind(documentInfo.SourceCodeKind); } return doc; }
// This is the string used to represent the FilePath property on a SyntaxTree object. // if the document does not yet have a file path, use the document's name instead. private static string GetSyntaxTreeFilePath(DocumentInfo info) { return(info.FilePath ?? info.Name); }