public AddAdditionalDocumentUndoUnit(
     VisualStudioWorkspaceImpl workspace,
     DocumentInfo docInfo,
     SourceText text)
     : base(workspace, docInfo, text)
 {
 }
Beispiel #2
0
        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);
        }
Beispiel #3
0
 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;
 }
Beispiel #5
0
 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;
 }
Beispiel #6
0
        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);
        }
Beispiel #7
0
 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);
        }
Beispiel #10
0
        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);
        }
Beispiel #11
0
        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;
        }
Beispiel #12
0
 public Solution AddAdditionalDocument(DocumentInfo documentInfo)
 {
     return(AddAdditionalDocuments(ImmutableArray.Create(documentInfo)));
 }
Beispiel #13
0
        /// <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);
        }
Beispiel #14
0
 public void AddDocument(DocumentInfo documentInfo)
 {
     OnDocumentAdded(documentInfo);
 }
Beispiel #15
0
        /// <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);
				});
			}
		}
Beispiel #17
0
 /// <summary>
 /// This method is called when a document is first observed.
 /// </summary>
 protected virtual void RegisterDocument(DocumentInfo documentInfo)
 {
 }
Beispiel #18
0
 // 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) { }
Beispiel #20
0
        // 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);
        }
Beispiel #21
0
        /// <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);
        }
Beispiel #22
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);
        }
        // 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) { }
Beispiel #25
0
        /// <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);
        }
Beispiel #26
0
        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);
        }
Beispiel #27
0
        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);
                }
            }
        }
Beispiel #28
0
        public Solution AddAdditionalDocument(DocumentInfo documentInfo)
        {
            var newState = _state.AddAdditionalDocument(documentInfo);
            if (newState == _state)
            {
                return this;
            }

            return new Solution(newState);
        }
Beispiel #29
0
        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);
        }
Beispiel #31
0
        /// <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)));
        }
Beispiel #32
0
        // 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);
		}
Beispiel #34
0
 // 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;
 }
Beispiel #35
0
        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;
        }
Beispiel #36
0
 // 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);
 }