Beispiel #1
0
        public bool TryGetLoaderFromProjectPath(string projectFilePath, DiagnosticReportingMode mode, out IProjectFileLoader loader)
        {
            using (_dataGuard.DisposableWait())
            {
                var extension = Path.GetExtension(projectFilePath);
                if (extension.Length > 0 && extension[0] == '.')
                {
                    extension = extension.Substring(1);
                }

                if (_extensionToLanguageMap.TryGetValue(extension, out var language))
                {
                    if (_workspaceServices.SupportedLanguages.Contains(language))
                    {
                        loader = _workspaceServices.GetLanguageServices(language).GetService <IProjectFileLoader>();
                    }
                    else
                    {
                        loader = null;
                        _diagnosticReporter.Report(mode, string.Format(WorkspacesResources.Cannot_open_project_0_because_the_language_1_is_not_supported, projectFilePath, language));
                        return(false);
                    }
                }
                else
                {
                    loader = ProjectFileLoader.GetLoaderForProjectFileExtension(_workspaceServices, extension);

                    if (loader == null)
                    {
                        _diagnosticReporter.Report(mode, string.Format(WorkspacesResources.Cannot_open_project_0_because_the_file_extension_1_is_not_associated_with_a_language, projectFilePath, Path.GetExtension(projectFilePath)));
                        return(false);
                    }
                }

                // since we have both C# and VB loaders in this same library, it no longer indicates whether we have full language support available.
                if (loader != null)
                {
                    language = loader.Language;

                    // check for command line parser existing... if not then error.
                    var commandLineParser = _workspaceServices
                                            .GetLanguageServices(language)
                                            .GetService <ICommandLineParserService>();

                    if (commandLineParser == null)
                    {
                        loader = null;
                        _diagnosticReporter.Report(mode, string.Format(WorkspacesResources.Cannot_open_project_0_because_the_language_1_is_not_supported, projectFilePath, language));
                        return(false);
                    }
                }

                return(loader != null);
            }
        }
 public static HostLanguageServices?GetLanguageServices(
     this HostWorkspaceServices workspaceServices,
     ITextBuffer textBuffer
     )
 {
     return(workspaceServices.GetLanguageServices(textBuffer.ContentType));
 }
Beispiel #3
0
        internal static IEnumerable <ClassifiedSpan> GetClassifiedSpans(
            HostWorkspaceServices workspaceServices,
            SemanticModel semanticModel,
            TextSpan textSpan,
            ClassificationOptions options,
            CancellationToken cancellationToken)
        {
            var service = workspaceServices.GetLanguageServices(semanticModel.Language).GetRequiredService <ISyntaxClassificationService>();

            var syntaxClassifiers = service.GetDefaultSyntaxClassifiers();

            var extensionManager    = workspaceServices.GetRequiredService <IExtensionManager>();
            var getNodeClassifiers  = extensionManager.CreateNodeExtensionGetter(syntaxClassifiers, c => c.SyntaxNodeTypes);
            var getTokenClassifiers = extensionManager.CreateTokenExtensionGetter(syntaxClassifiers, c => c.SyntaxTokenKinds);

            using var _1 = ArrayBuilder <ClassifiedSpan> .GetInstance(out var syntacticClassifications);

            using var _2 = ArrayBuilder <ClassifiedSpan> .GetInstance(out var semanticClassifications);

            var root = semanticModel.SyntaxTree.GetRoot(cancellationToken);

            service.AddSyntacticClassifications(root, textSpan, syntacticClassifications, cancellationToken);
            service.AddSemanticClassifications(semanticModel, textSpan, getNodeClassifiers, getTokenClassifiers, semanticClassifications, options, cancellationToken);

            var allClassifications = new List <ClassifiedSpan>(semanticClassifications.Where(s => s.TextSpan.OverlapsWith(textSpan)));
            var semanticSet        = semanticClassifications.Select(s => s.TextSpan).ToSet();

            allClassifications.AddRange(syntacticClassifications.Where(
                                            s => s.TextSpan.OverlapsWith(textSpan) && !semanticSet.Contains(s.TextSpan)));
            allClassifications.Sort((s1, s2) => s1.TextSpan.Start - s2.TextSpan.Start);

            return(allClassifications);
        }
Beispiel #4
0
        /// <summary>
        /// Clean up the provided spans in the node.
        /// This will only cleanup stuff that doesn't require semantic information.
        /// </summary>
        public static Task <SyntaxNode> CleanupAsync(SyntaxNode root, ImmutableArray <TextSpan> spans, SyntaxFormattingOptions options, HostWorkspaceServices services, ImmutableArray <ICodeCleanupProvider> providers = default, CancellationToken cancellationToken = default)
        {
            var languageServices = services.GetLanguageServices(root.Language);
            var cleanupService   = languageServices.GetRequiredService <ICodeCleanerService>();

            return(cleanupService.CleanupAsync(root, spans, options, services, providers, cancellationToken));
        }
        private static Dictionary <string, string> CreateContentTypeMap(HostWorkspaceServices hostWorkspaceServices)
        {
            // Are we being hosted in a MEF host? If so, we can get content type information directly from the
            // metadata and avoid actually loading the assemblies
            var mefHostServices = (IMefHostExportProvider)hostWorkspaceServices.HostServices;

            if (mefHostServices != null)
            {
                // Two assemblies may export the same language to content type mapping during development cycles where
                // a type is moving to a new assembly. Avoid failing during content type discovery by de-duplicating
                // services with identical metadata, opting to instead fail only in cases where the impacted service
                // instance is used.
                var exports = mefHostServices.GetExports <ILanguageService, ContentTypeLanguageMetadata>();
                return(exports
                       .Where(lz => !string.IsNullOrEmpty(lz.Metadata.DefaultContentType))
                       .Select(lz => (lz.Metadata.Language, lz.Metadata.DefaultContentType))
                       .Distinct()
                       .ToDictionary(lz => lz.Language, lz => lz.DefaultContentType));
            }

            // We can't do anything special, so fall back to the expensive path
            return(hostWorkspaceServices.SupportedLanguages.ToDictionary(
                       l => l,
                       l => hostWorkspaceServices.GetLanguageServices(l).GetRequiredService <IContentTypeLanguageService>().GetDefaultContentType().TypeName));
        }
Beispiel #6
0
 private IOptionsSerializationService GetOptionsSerializationService(string languageName) =>
 _lazyLanguageSerializationService.GetOrAdd(
     languageName,
     n =>
     _workspaceServices
     .GetLanguageServices(n)
     .GetRequiredService <IOptionsSerializationService>()
     );
#pragma warning disable RS0030 // Do not used banned API 'GetLanguageServices', use 'GetExtendedLanguageServices' instead - allow in this helper which computes the extended language services.
        /// <summary>
        /// Gets extended host language services, which includes language services from <see cref="HostWorkspaceServices.GetLanguageServices(string)"/>.
        /// </summary>
        public static HostLanguageServices GetExtendedLanguageServices(this HostWorkspaceServices hostWorkspaceServices, string languageName)
        {
            var languageServices = hostWorkspaceServices.GetLanguageServices(languageName);

#if CODE_STYLE
            languageServices = CodeStyleHostLanguageServices.GetRequiredMappedCodeStyleLanguageServices(languageServices);
#endif
            return(languageServices);
        }
Beispiel #8
0
        public VisualStudioProjectOptionsProcessor(VisualStudioProject project, HostWorkspaceServices workspaceServices)
        {
            _project                  = project ?? throw new ArgumentNullException(nameof(project));
            _workspaceServices        = workspaceServices;
            _commandLineParserService = workspaceServices.GetLanguageServices(project.Language).GetRequiredService <ICommandLineParserService>();

            // Set up _commandLineArgumentsForCommandLine to a default. No lock taken since we're in the constructor so nothing can race.
            ReparseCommandLine_NoLock();
        }
Beispiel #9
0
        public static HostLanguageServices GetExtendedLanguageServices(this HostWorkspaceServices hostWorkspaceServices, string languageName)
        {
            var languageServices = hostWorkspaceServices.GetLanguageServices(languageName);

#if CODE_STYLE
            // TODO: Uncomment the below once we enable language service detection in CodeStyle layer.
            //languageServices = CodeStyleHostLanguageServices.GetRequiredMappedCodeStyleLanguageServices(languageServices);
#endif
            return(languageServices);
        }
Beispiel #10
0
        public override HostLanguageServices GetLanguageServices(string languageName)
        {
            if (languageName == RazorLanguage.Name)
            {
                return(_razorLanguageServices);
            }

            // Fallback to default host services to resolve roslyn specific features.
            return(_fallbackServices.GetLanguageServices(languageName));
        }
Beispiel #11
0
        private static Task <SyntaxToken> GetTokenAtPositionAsync(
            SemanticModel semanticModel,
            int position,
            HostWorkspaceServices services,
            CancellationToken cancellationToken)
        {
            var syntaxTree  = semanticModel.SyntaxTree;
            var syntaxFacts = services.GetLanguageServices(semanticModel.Language).GetRequiredService <ISyntaxFactsService>();

            return(syntaxTree.GetTouchingTokenAsync(position, syntaxFacts.IsBindableToken, cancellationToken, findInsideTrivia: true));
        }
        internal static ProjectInfo CreateMiscellaneousProjectInfoForDocument(
            string filePath,
            TextLoader textLoader,
            LanguageInformation languageInformation,
            HostWorkspaceServices services,
            ImmutableArray <MetadataReference> metadataReferences)
        {
            var fileExtension = PathUtilities.GetExtension(filePath);

            var languageServices   = services.GetLanguageServices(languageInformation.LanguageName);
            var compilationOptions = languageServices.GetService <ICompilationFactoryService>()?.GetDefaultCompilationOptions();

            // Use latest language version which is more permissive, as we cannot find out language version of the project which the file belongs to
            // https://devdiv.visualstudio.com/DevDiv/_workitems/edit/575761
            var parseOptions = languageServices.GetService <ISyntaxTreeFactoryService>()?.GetDefaultParseOptionsWithLatestLanguageVersion();

            if (parseOptions != null &&
                compilationOptions != null &&
                fileExtension == languageInformation.ScriptExtension)
            {
                parseOptions       = parseOptions.WithKind(SourceCodeKind.Script);
                compilationOptions = GetCompilationOptionsWithScriptReferenceResolvers(services, compilationOptions, filePath);
            }

            var projectId  = ProjectId.CreateNewId(debugName: "Miscellaneous Files Project for " + filePath);
            var documentId = DocumentId.CreateNewId(projectId, debugName: filePath);

            var sourceCodeKind = parseOptions?.Kind ?? SourceCodeKind.Regular;
            var documentInfo   = DocumentInfo.Create(
                documentId,
                filePath,
                sourceCodeKind: sourceCodeKind,
                loader: textLoader,
                filePath: filePath);

            // The assembly name must be unique for each collection of loose files. Since the name doesn't matter
            // a random GUID can be used.
            var assemblyName = Guid.NewGuid().ToString("N");

            var projectInfo = ProjectInfo.Create(
                projectId,
                VersionStamp.Create(),
                name: FeaturesResources.Miscellaneous_Files,
                assemblyName,
                languageInformation.LanguageName,
                compilationOptions: compilationOptions,
                parseOptions: parseOptions,
                documents: SpecializedCollections.SingletonEnumerable(documentInfo),
                metadataReferences: metadataReferences);

            // Miscellaneous files projects are never fully loaded since, by definition, it won't know
            // what the full set of information is except when the file is script code.
            return(projectInfo.WithHasAllInformation(hasAllInformation: sourceCodeKind == SourceCodeKind.Script));
        }
Beispiel #13
0
        public static HostLanguageServices GetLanguageServices(
            this HostWorkspaceServices workspaceServices, IContentType contentType)
        {
            foreach (var language in workspaceServices.SupportedLanguages)
            {
                if (LanguageMatches(language, contentType, workspaceServices))
                {
                    return(workspaceServices.GetLanguageServices(language));
                }
            }

            return(null);
        }
        /// <summary>
        /// Returns true if the character recently inserted or deleted in the text should trigger completion.
        /// </summary>
        /// <param name="text">The document text to trigger completion within </param>
        /// <param name="caretPosition">The position of the caret after the triggering action.</param>
        /// <param name="trigger">The potential triggering action.</param>
        /// <param name="roles">Optional set of roles associated with the editor state.</param>
        /// <param name="options">Optional options that override the default options.</param>
        /// <remarks>
        /// This API uses SourceText instead of Document so implementations can only be based on text, not syntax or semantics.
        /// </remarks>
        public bool ShouldTriggerCompletion(
            SourceText text,
            int caretPosition,
            CompletionTrigger trigger,
            ImmutableHashSet <string>?roles = null,
            OptionSet?options = null)
        {
            var document         = text.GetOpenDocumentInCurrentContextWithChanges();
            var languageServices = document?.Project.LanguageServices ?? _services.GetLanguageServices(Language);

            // Publicly available options do not affect this API.
            var completionOptions  = CompletionOptions.Default;
            var passThroughOptions = options ?? document?.Project.Solution.Options ?? OptionValueSet.Empty;

            return(ShouldTriggerCompletion(document?.Project, languageServices, text, caretPosition, trigger, completionOptions, passThroughOptions, roles));
        }
        public VisualStudioProjectOptionsProcessor(
            VisualStudioProject project,
            HostWorkspaceServices workspaceServices)
        {
            _project                  = project ?? throw new ArgumentNullException(nameof(project));
            _workspaceServices        = workspaceServices;
            _commandLineParserService = workspaceServices.GetLanguageServices(project.Language).GetRequiredService <ICommandLineParserService>();
            _temporaryStorageService  = workspaceServices.GetRequiredService <ITemporaryStorageService>();

            // Set up _commandLineArgumentsForCommandLine to a default. No lock taken since we're in
            // the constructor so nothing can race.

            // Silence NRT warning.  This will be initialized by the call below to ReparseCommandLineIfChanged_NoLock.
            _commandLineArgumentsForCommandLine = null !;
            ReparseCommandLineIfChanged_NoLock(commandLine: "");
        }
Beispiel #16
0
        public VisualStudioProjectOptionsProcessor(VisualStudioProject project, HostWorkspaceServices workspaceServices)
        {
            _project                  = project ?? throw new ArgumentNullException(nameof(project));
            _workspaceServices        = workspaceServices;
            _commandLineParserService = workspaceServices.GetLanguageServices(project.Language).GetRequiredService <ICommandLineParserService>();

            // Set up _commandLineArgumentsForCommandLine to a default. No lock taken since we're in the constructor so nothing can race.
            ReparseCommandLine_NoLock();

            _optionService = workspaceServices.GetRequiredService <IOptionService>();

            // For C#, we need to listen to the options for NRT analysis
            // that can change in VS through tools > options
            if (_project.Language == LanguageNames.CSharp)
            {
                _optionService.OptionChanged += OptionService_OptionChanged;
            }
        }
Beispiel #17
0
        private static Dictionary <string, string> CreateContentTypeMap(HostWorkspaceServices hostWorkspaceServices)
        {
            // Are we being hosted in a MEF host? If so, we can get content type information directly from the
            // metadata and avoid actually loading the assemblies
            var mefHostServices = (IMefHostExportProvider)hostWorkspaceServices.HostServices;

            if (mefHostServices != null)
            {
                var registry = mefHostServices.GetExports <IContentTypeRegistryService>().Single().Value;
                return(mefHostServices.GetExports <ILanguageService, ContentTypeLanguageMetadata>()
                       .Where(lz => !string.IsNullOrEmpty(lz.Metadata.DefaultContentType))
                       .ToDictionary(lz => lz.Metadata.Language, lz => lz.Metadata.DefaultContentType));
            }

            // We can't do anything special, so fall back to the expensive path
            return(hostWorkspaceServices.SupportedLanguages.ToDictionary(
                       l => l,
                       l => hostWorkspaceServices.GetLanguageServices(l).GetRequiredService <IContentTypeLanguageService>().GetDefaultContentType().TypeName));
        }
Beispiel #18
0
        public static async Task <QuickInfoItem> CreateQuickInfoItemAsync(
            HostWorkspaceServices services,
            SemanticModel semanticModel,
            TextSpan span,
            ImmutableArray <ISymbol> symbols,
            SupportedPlatformData?supportedPlatforms,
            bool showAwaitReturn,
            NullableFlowState flowState,
            SymbolDescriptionOptions options,
            CancellationToken cancellationToken)
        {
            var descriptionService = services.GetLanguageServices(semanticModel.Language).GetRequiredService <ISymbolDisplayService>();
            var groups             = await descriptionService.ToDescriptionGroupsAsync(semanticModel, span.Start, symbols, options, cancellationToken).ConfigureAwait(false);

            using var _1 = ArrayBuilder <QuickInfoSection> .GetInstance(out var sections);

            var symbol = symbols.First();

            if (showAwaitReturn)
            {
                // We show a special message if the Task being awaited has no return
                if (symbol is INamedTypeSymbol {
                    SpecialType : SpecialType.System_Void
                })
Beispiel #19
0
 private TLanguageService GetLanguageService <TLanguageService>(string languageName)
     where TLanguageService : ILanguageService
 => _workspaceServices
 .GetLanguageServices(languageName)
 .GetService <TLanguageService>();
 internal ValueTask <TOptions> GetOptionsAsync(string language, CancellationToken cancellationToken)
 => _optionsProvider.GetOptionsAsync(_services.GetLanguageServices(language), cancellationToken);
        public static TokenSemanticInfo GetSemanticInfo(
            this SemanticModel semanticModel,
            SyntaxToken token,
            HostWorkspaceServices services,
            CancellationToken cancellationToken)
        {
            var languageServices = services.GetLanguageServices(token.Language);
            var syntaxFacts      = languageServices.GetRequiredService <ISyntaxFactsService>();

            if (!syntaxFacts.IsBindableToken(token))
            {
                return(TokenSemanticInfo.Empty);
            }

            var semanticFacts = languageServices.GetRequiredService <ISemanticFactsService>();

            IAliasSymbol?aliasSymbol;
            ITypeSymbol? type;
            ITypeSymbol? convertedType;
            ISymbol?     declaredSymbol;
            ImmutableArray <ISymbol?> allSymbols;

            var overriddingIdentifier = syntaxFacts.GetDeclarationIdentifierIfOverride(token);

            if (overriddingIdentifier.HasValue)
            {
                // on an "override" token, we'll find the overridden symbol
                aliasSymbol = null;
                var overriddingSymbol = semanticFacts.GetDeclaredSymbol(semanticModel, overriddingIdentifier.Value, cancellationToken);
                var overriddenSymbol  = overriddingSymbol.GetOverriddenMember();

                // on an "override" token, the overridden symbol is the only part of TokenSemanticInfo used by callers, so type doesn't matter
                type           = null;
                convertedType  = null;
                declaredSymbol = null;
                allSymbols     = overriddenSymbol is null ? ImmutableArray <ISymbol?> .Empty : ImmutableArray.Create <ISymbol?>(overriddenSymbol);
            }
            else
            {
                aliasSymbol = semanticModel.GetAliasInfo(token.Parent !, cancellationToken);
                var bindableParent = syntaxFacts.TryGetBindableParent(token);
                var typeInfo       = bindableParent != null?semanticModel.GetTypeInfo(bindableParent, cancellationToken) : default;

                type           = typeInfo.Type;
                convertedType  = typeInfo.ConvertedType;
                declaredSymbol = MapSymbol(semanticFacts.GetDeclaredSymbol(semanticModel, token, cancellationToken), type);

                var skipSymbolInfoLookup = declaredSymbol.IsKind(SymbolKind.RangeVariable);
                allSymbols = skipSymbolInfoLookup
                    ? ImmutableArray <ISymbol?> .Empty
                    : semanticFacts
                             .GetBestOrAllSymbols(semanticModel, bindableParent, token, cancellationToken)
                             .WhereAsArray(s => !s.Equals(declaredSymbol))
                             .SelectAsArray(s => MapSymbol(s, type));
            }

            // NOTE(cyrusn): This is a workaround to how the semantic model binds and returns
            // information for VB event handlers.  Namely, if you have:
            //
            // Event X]()
            // Sub Goo()
            //      Dim y = New $$XEventHandler(AddressOf bar)
            // End Sub
            //
            // Only GetTypeInfo will return any information for XEventHandler.  So, in this
            // case, we upgrade the type to be the symbol we return.
            if (type != null && allSymbols.Length == 0)
            {
                if (type.Kind == SymbolKind.NamedType)
                {
                    var namedType = (INamedTypeSymbol)type;
                    if (namedType.TypeKind == TypeKind.Delegate ||
                        namedType.AssociatedSymbol != null)
                    {
                        allSymbols = ImmutableArray.Create <ISymbol?>(type);
                        type       = null;
                    }
                }
            }

            if (allSymbols.Length == 0 && syntaxFacts.IsQueryKeyword(token))
            {
                type          = null;
                convertedType = null;
            }

            return(new TokenSemanticInfo(declaredSymbol, aliasSymbol, allSymbols, type, convertedType, token.Span));
        }
        private AbstractProject GetOrCreateProjectFromArgumentsAndReferences(
            IWorkspaceProjectContextFactory workspaceProjectContextFactory,
            IAnalyzerAssemblyLoader analyzerAssemblyLoader,
            string projectFilename,
            IReadOnlyDictionary <string, DeferredProjectInformation> allProjectInfos,
            IReadOnlyDictionary <string, string> targetPathsToProjectPaths)
        {
            var languageName = GetLanguageOfProject(projectFilename);

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

            if (!allProjectInfos.TryGetValue(projectFilename, out var projectInfo))
            {
                // This could happen if we were called recursively about a dangling P2P reference
                // that isn't actually in the solution.
                return(null);
            }

            var commandLineParser    = _workspaceServices.GetLanguageServices(languageName).GetService <ICommandLineParserService>();
            var projectDirectory     = PathUtilities.GetDirectoryName(projectFilename);
            var commandLineArguments = commandLineParser.Parse(
                projectInfo.CommandLineArguments,
                projectDirectory,
                isInteractive: false,
                sdkDirectory: RuntimeEnvironment.GetRuntimeDirectory());

            // TODO: Should come from sln file?
            var projectName = PathUtilities.GetFileName(projectFilename, includeExtension: false);

            // `AbstractProject` only sets the filename if it actually exists.  Since we want
            // our ids to match, mimic that behavior here.
            var projectId = File.Exists(projectFilename)
                ? GetOrCreateProjectIdForPath(projectFilename, projectName)
                : GetOrCreateProjectIdForPath(projectName, projectName);

            // See if we've already created this project and we're now in a recursive call to
            // hook up a P2P ref.
            if (_projectMap.TryGetValue(projectId, out var project))
            {
                return(project);
            }

            OutputToOutputWindow($"\tCreating '{projectName}':\t{commandLineArguments.SourceFiles.Length} source files,\t{commandLineArguments.MetadataReferences.Length} references.");
            var solution5 = _serviceProvider.GetService(typeof(SVsSolution)) as IVsSolution5;

            // If the index is stale, it might give us a path that doesn't exist anymore that the
            // solution doesn't know about - be resilient to that case.
            Guid projectGuid;

            try
            {
                projectGuid = solution5.GetGuidOfProjectFile(projectFilename);
            }
            catch (ArgumentException)
            {
                var message = $"Failed to get the project guid for '{projectFilename}' from the solution, using  random guid instead.";
                Debug.Fail(message);
                OutputToOutputWindow(message);
                projectGuid = Guid.NewGuid();
            }

            // NOTE: If the indexing service fails for a project, it will give us an *empty*
            // target path, which we aren't prepared to handle.  Instead, convert it to a *null*
            // value, which we do handle.
            var outputPath = projectInfo.TargetPath;

            if (outputPath == string.Empty)
            {
                outputPath = null;
            }

            var projectContext = workspaceProjectContextFactory.CreateProjectContext(
                languageName,
                projectName,
                projectFilename,
                projectGuid: projectGuid,
                hierarchy: null,
                binOutputPath: outputPath);

            project = (AbstractProject)projectContext;
            projectContext.SetOptions(projectInfo.CommandLineArguments.Join(" "));

            foreach (var sourceFile in commandLineArguments.SourceFiles)
            {
                projectContext.AddSourceFile(sourceFile.Path);
            }

            foreach (var sourceFile in commandLineArguments.AdditionalFiles)
            {
                projectContext.AddAdditionalFile(sourceFile.Path);
            }

            var metadataReferences     = commandLineArguments.ResolveMetadataReferences(project.CurrentCompilationOptions.MetadataReferenceResolver).AsImmutable();
            var addedProjectReferences = new HashSet <string>();

            foreach (var projectReferencePath in projectInfo.ReferencedProjectFilePaths)
            {
                var referencedProject = TryFindExistingProjectForProjectReference(projectReferencePath, metadataReferences);
                if (referencedProject == null)
                {
                    referencedProject = GetOrCreateProjectFromArgumentsAndReferences(
                        workspaceProjectContextFactory,
                        analyzerAssemblyLoader,
                        projectReferencePath,
                        allProjectInfos,
                        targetPathsToProjectPaths);
                }

                var referencedProjectContext = referencedProject as IWorkspaceProjectContext;
                if (referencedProjectContext != null)
                {
                    // TODO: Can we get the properties from corresponding metadata reference in
                    // commandLineArguments?
                    addedProjectReferences.Add(projectReferencePath);
                    projectContext.AddProjectReference(
                        referencedProjectContext,
                        new MetadataReferenceProperties());
                }
                else if (referencedProject != null)
                {
                    // This project was already created by the regular project system. See if we
                    // can find the matching project somehow.
                    var existingReferenceOutputPath = referencedProject?.BinOutputPath;
                    if (existingReferenceOutputPath != null)
                    {
                        addedProjectReferences.Add(projectReferencePath);
                        projectContext.AddMetadataReference(
                            existingReferenceOutputPath,
                            new MetadataReferenceProperties());
                    }
                }
                else
                {
                    // We don't know how to create this project.  Another language or something?
                    OutputToOutputWindow($"Failed to create a project for '{projectReferencePath}'.");
                }
            }

            foreach (var reference in metadataReferences)
            {
                var path = GetReferencePath(reference);
                if (targetPathsToProjectPaths.TryGetValue(path, out var possibleProjectReference) &&
                    addedProjectReferences.Contains(possibleProjectReference))
                {
                    // We already added a P2P reference for this, we don't need to add the file reference too.
                    continue;
                }

                projectContext.AddMetadataReference(path, reference.Properties);
            }

            foreach (var reference in commandLineArguments.ResolveAnalyzerReferences(analyzerAssemblyLoader))
            {
                var path = reference.FullPath;
                if (!PathUtilities.IsAbsolute(path))
                {
                    path = PathUtilities.CombineAbsoluteAndRelativePaths(
                        projectDirectory,
                        path);
                }

                projectContext.AddAnalyzerReference(path);
            }

            return((AbstractProject)projectContext);
        }
        private AbstractProject GetOrCreateProjectFromArgumentsAndReferences(
            IWorkspaceProjectContextFactory workspaceProjectContextFactory,
            IAnalyzerAssemblyLoader analyzerAssemblyLoader,
            string projectFilename,
            IReadOnlyDictionary <string, DeferredProjectInformation> allProjectInfos,
            IReadOnlyDictionary <string, string> targetPathsToProjectPaths)
        {
            var languageName = GetLanguageOfProject(projectFilename);

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

            if (!allProjectInfos.TryGetValue(projectFilename, out var projectInfo))
            {
                // This could happen if we were called recursively about a dangling P2P reference
                // that isn't actually in the solution.
                return(null);
            }

            // TODO: Should come from .sln file?
            var projectName = PathUtilities.GetFileName(projectFilename, includeExtension: false);

            // `AbstractProject` only sets the filename if it actually exists.  Since we want
            // our ids to match, mimic that behavior here.
            var projectId = File.Exists(projectFilename)
                ? GetOrCreateProjectIdForPath(projectFilename, projectName)
                : GetOrCreateProjectIdForPath(projectName, projectName);

            // See if something has already created this project - it's not deferred, the AnyCode design time build
            // failed so we force loaded it, or we already created a deferred project and we're in a recursive call
            // to find a ProjectReference
            if (_projectMap.TryGetValue(projectId, out var project))
            {
                return(project);
            }

            // If the project system has opted this project out of deferred loading, or AnyCode
            // was unable to get command line info for it, we can't create a project for it.
            // NOTE: We need to check this even though it happened in CreateDeferredProjects
            // because we could be in a recursive call from a project reference below.
            var solution7 = (IVsSolution7)_vsSolution;

            if (DesignTimeBuildFailed(projectInfo) ||
                !solution7.IsDeferredProjectLoadAllowed(projectFilename))
            {
                return(null);
            }

            var commandLineParser    = _workspaceServices.GetLanguageServices(languageName).GetService <ICommandLineParserService>();
            var projectDirectory     = PathUtilities.GetDirectoryName(projectFilename);
            var commandLineArguments = commandLineParser.Parse(
                projectInfo.CommandLineArguments,
                projectDirectory,
                isInteractive: false,
                sdkDirectory: RuntimeEnvironment.GetRuntimeDirectory());

            OutputToOutputWindow($"\tCreating '{projectName}':\t{commandLineArguments.SourceFiles.Length} source files,\t{commandLineArguments.MetadataReferences.Length} references.");

            var projectGuid    = GetProjectGuid(projectFilename);
            var projectContext = workspaceProjectContextFactory.CreateProjectContext(
                languageName,
                projectName,
                projectFilename,
                projectGuid: projectGuid,
                hierarchy: null,
                binOutputPath: projectInfo.TargetPath);

            project = (AbstractProject)projectContext;
            projectContext.SetOptions(projectInfo.CommandLineArguments.Join(" "));

            var addedSourceFilePaths = new HashSet <string>(StringComparer.OrdinalIgnoreCase);

            foreach (var sourceFile in commandLineArguments.SourceFiles)
            {
                if (addedSourceFilePaths.Add(sourceFile.Path))
                {
                    projectContext.AddSourceFile(sourceFile.Path);
                }
            }

            var addedAdditionalFilePaths = new HashSet <string>(StringComparer.OrdinalIgnoreCase);

            foreach (var additionalFile in commandLineArguments.AdditionalFiles)
            {
                if (addedAdditionalFilePaths.Add(additionalFile.Path))
                {
                    projectContext.AddAdditionalFile(additionalFile.Path);
                }
            }

            var metadataReferences     = commandLineArguments.ResolveMetadataReferences(project.CurrentCompilationOptions.MetadataReferenceResolver).AsImmutable();
            var addedProjectReferences = new HashSet <string>();

            foreach (var projectReferencePath in projectInfo.ReferencedProjectFilePaths)
            {
                var referencedProject = TryFindExistingProjectForProjectReference(projectReferencePath, metadataReferences);
                if (referencedProject == null)
                {
                    referencedProject = GetOrCreateProjectFromArgumentsAndReferences(
                        workspaceProjectContextFactory,
                        analyzerAssemblyLoader,
                        projectReferencePath,
                        allProjectInfos,
                        targetPathsToProjectPaths);
                }

                var referencedProjectContext = referencedProject as IWorkspaceProjectContext;
                if (referencedProjectContext != null)
                {
                    // TODO: Can we get the properties from corresponding metadata reference in
                    // commandLineArguments?
                    addedProjectReferences.Add(projectReferencePath);
                    projectContext.AddProjectReference(
                        referencedProjectContext,
                        new MetadataReferenceProperties());
                }
                else if (referencedProject != null)
                {
                    // This project was already created by the regular project system. See if we
                    // can find the matching project somehow.
                    var existingReferenceOutputPath = referencedProject?.BinOutputPath;
                    if (existingReferenceOutputPath != null)
                    {
                        addedProjectReferences.Add(projectReferencePath);
                        projectContext.AddMetadataReference(
                            existingReferenceOutputPath,
                            new MetadataReferenceProperties());
                    }
                }
                else
                {
                    // We don't know how to create this project.  Another language or something?
                    OutputToOutputWindow($"\t\tFailed to create a project for '{projectReferencePath}'.");
                }
            }

            var addedReferencePaths = new HashSet <string>(StringComparer.OrdinalIgnoreCase);

            foreach (var reference in metadataReferences)
            {
                var path = GetReferencePath(reference);
                if (targetPathsToProjectPaths.TryGetValue(path, out var possibleProjectReference) &&
                    addedProjectReferences.Contains(possibleProjectReference))
                {
                    // We already added a P2P reference for this, we don't need to add the file reference too.
                    continue;
                }

                if (addedReferencePaths.Add(path))
                {
                    projectContext.AddMetadataReference(path, reference.Properties);
                }
            }

            var addedAnalyzerPaths = new HashSet <string>(StringComparer.OrdinalIgnoreCase);

            foreach (var reference in commandLineArguments.ResolveAnalyzerReferences(analyzerAssemblyLoader))
            {
                var path = reference.FullPath;
                if (!PathUtilities.IsAbsolute(path))
                {
                    path = PathUtilities.CombineAbsoluteAndRelativePaths(
                        projectDirectory,
                        path);
                }

                if (addedAnalyzerPaths.Add(path))
                {
                    projectContext.AddAnalyzerReference(path);
                }
            }

            return((AbstractProject)projectContext);
        }
Beispiel #24
0
 private IOptionsSerializationService GetOptionsSerializationService(string languageName)
 {
     return(_lazyLanguageSerializationService.GetOrAdd(languageName, n => _workspaceServices.GetLanguageServices(n).GetService <IOptionsSerializationService>()));
 }
        public static async Task <CompletionDescription> CreateDescriptionAsync(
            HostWorkspaceServices workspaceServices, SemanticModel semanticModel, int position, ISymbol symbol, int overloadCount, SymbolDescriptionOptions options, SupportedPlatformData?supportedPlatforms, CancellationToken cancellationToken)
        {
            var symbolDisplayService = workspaceServices.GetLanguageServices(semanticModel.Language).GetRequiredService <ISymbolDisplayService>();
            var formatter            = workspaceServices.GetLanguageServices(semanticModel.Language).GetRequiredService <IDocumentationCommentFormattingService>();

            // TODO(cyrusn): Figure out a way to cancel this.
            var sections = await symbolDisplayService.ToDescriptionGroupsAsync(semanticModel, position, ImmutableArray.Create(symbol), options, cancellationToken).ConfigureAwait(false);

            if (!sections.ContainsKey(SymbolDescriptionGroups.MainDescription))
            {
                return(CompletionDescription.Empty);
            }

            var textContentBuilder = new List <TaggedText>();

            textContentBuilder.AddRange(sections[SymbolDescriptionGroups.MainDescription]);

            switch (symbol.Kind)
            {
            case SymbolKind.Method:
            case SymbolKind.Property:
            case SymbolKind.NamedType:
                if (overloadCount > 0)
                {
                    var isGeneric = symbol.GetArity() > 0;

                    textContentBuilder.AddSpace();
                    textContentBuilder.AddPunctuation("(");
                    textContentBuilder.AddPunctuation("+");
                    textContentBuilder.AddText(NonBreakingSpaceString + overloadCount.ToString());

                    AddOverloadPart(textContentBuilder, overloadCount, isGeneric);

                    textContentBuilder.AddPunctuation(")");
                }

                break;
            }

            AddDocumentationPart(textContentBuilder, symbol, semanticModel, position, formatter, cancellationToken);

            if (sections.TryGetValue(SymbolDescriptionGroups.AwaitableUsageText, out var parts))
            {
                textContentBuilder.AddRange(parts);
            }

            if (sections.TryGetValue(SymbolDescriptionGroups.StructuralTypes, out parts))
            {
                if (!parts.IsDefaultOrEmpty)
                {
                    textContentBuilder.AddLineBreak();
                    textContentBuilder.AddLineBreak();
                    textContentBuilder.AddRange(parts);
                }
            }

            if (supportedPlatforms != null)
            {
                textContentBuilder.AddLineBreak();
                textContentBuilder.AddRange(supportedPlatforms.ToDisplayParts().ToTaggedText());
            }

            return(CompletionDescription.Create(textContentBuilder.AsImmutable()));
        }
Beispiel #26
0
        protected Document CreateDocument(DocumentId documentId, string languageName, SourceText sourceText, string filePath)
        {
            var languageServices = _services.GetLanguageServices(languageName);

            return(new Document(languageServices, documentId, sourceText, filePath, null, null, null));
        }
Beispiel #27
0
        protected Document CreateDocument(DocumentId documentId, string languageName, SourceFile file)
        {
            var languageServices = _services.GetLanguageServices(languageName);

            return(new Document(languageServices, documentId, file));
        }
        private async Task <IReadOnlyList <TagHelperDescriptor> > GetTagHelperInitializationTaskCore(ProjectSnapshot snapshot)
        {
            var resolver = _services.GetLanguageServices(RazorLanguage.Name).GetRequiredService <TagHelperResolver>();

            return((await resolver.GetTagHelpersAsync(snapshot)).Descriptors);
        }