/// <summary>
        /// Parses a <see cref="StackFrameNameNode"/> which could either be a <see cref="StackFrameSimpleNameNode"/> or <see cref="StackFrameQualifiedNameNode" />.
        ///
        /// Nodes will be parsed for arity but not generic type arguments.
        ///
        /// <code>
        /// All of the following are valid nodes, where "$$" marks the parsing starting point, and "[|" + "|]" mark the endpoints of the parsed node excluding trivia
        ///   * [|$$MyNamespace.MyClass.MyMethod|](string s)
        ///   * MyClass.MyMethod([|$$string|] s)
        ///   * MyClass.MyMethod([|$$string[]|] s)
        ///   * [|$$MyClass`1.MyMethod|](string s)
        ///   * [|$$MyClass.MyMethod|][T](T t)
        /// </code>
        ///
        /// </summary>
        private StackFrameNameNode?TryParseRequiredNameNode(bool scanAtTrivia)
        {
            var currentIdentifer = _lexer.TryScanIdentifier(scanAtTrivia: scanAtTrivia, scanLeadingWhitespace: true, scanTrailingWhitespace: false);

            if (!currentIdentifer.HasValue)
            {
                return(null);
            }

            var(success, genericIdentifier) = TryScanGenericTypeIdentifier(currentIdentifer.Value);
            if (!success)
            {
                return(null);
            }

            RoslynDebug.AssertNotNull(genericIdentifier);
            StackFrameNameNode nameNode = genericIdentifier;

            while (true)
            {
                (success, var memberAccess) = TryParseQualifiedName(nameNode);
                if (!success)
                {
                    return(null);
                }

                if (memberAccess is null)
                {
                    Debug.Assert(nameNode is StackFrameQualifiedNameNode or StackFrameSimpleNameNode);
                    return(nameNode);
                }

                nameNode = memberAccess;
            }
        }
Beispiel #2
0
        internal static ImmutableArray <PortableExecutableReference> ResolveMetadataReference(CommandLineReference cmdReference, MetadataReferenceResolver metadataResolver, List <DiagnosticInfo>?diagnosticsOpt, CommonMessageProvider?messageProviderOpt)
        {
            RoslynDebug.Assert(metadataResolver != null);
            Debug.Assert((diagnosticsOpt == null) == (messageProviderOpt == null));

            ImmutableArray <PortableExecutableReference> references;

            try
            {
                references = metadataResolver.ResolveReference(cmdReference.Reference, baseFilePath: null, properties: cmdReference.Properties);
            }
            catch (Exception e) when(diagnosticsOpt != null && (e is BadImageFormatException || e is IOException))
            {
                var diagnostic = PortableExecutableReference.ExceptionToDiagnostic(e, messageProviderOpt !, Location.None, cmdReference.Reference, cmdReference.Properties.Kind);

                diagnosticsOpt.Add(((DiagnosticWithInfo)diagnostic).Info);
                return(ImmutableArray <PortableExecutableReference> .Empty);
            }

            if (references.IsDefaultOrEmpty && diagnosticsOpt != null)
            {
                RoslynDebug.AssertNotNull(messageProviderOpt);
                diagnosticsOpt.Add(new DiagnosticInfo(messageProviderOpt, messageProviderOpt.ERR_MetadataFileNotFound, cmdReference.Reference));
                return(ImmutableArray <PortableExecutableReference> .Empty);
            }

            return(references);
        }
Beispiel #3
0
        public MethodDebugInfo(
            ImmutableArray <HoistedLocalScopeRecord> hoistedLocalScopeRecords,
            ImmutableArray <ImmutableArray <ImportRecord> > importRecordGroups,
            ImmutableArray <ExternAliasRecord> externAliasRecords,
            ImmutableDictionary <int, ImmutableArray <bool> >?dynamicLocalMap,
            ImmutableDictionary <int, ImmutableArray <string?> >?tupleLocalMap,
            string defaultNamespaceName,
            ImmutableArray <string> localVariableNames,
            ImmutableArray <TLocalSymbol> localConstants,
            ILSpan reuseSpan)
        {
            RoslynDebug.Assert(!importRecordGroups.IsDefault);
            RoslynDebug.Assert(!externAliasRecords.IsDefault);
            RoslynDebug.AssertNotNull(defaultNamespaceName);

            HoistedLocalScopeRecords = hoistedLocalScopeRecords;
            ImportRecordGroups       = importRecordGroups;

            ExternAliasRecords = externAliasRecords;
            DynamicLocalMap    = dynamicLocalMap;
            TupleLocalMap      = tupleLocalMap;

            DefaultNamespaceName = defaultNamespaceName;

            LocalVariableNames = localVariableNames;
            LocalConstants     = localConstants;
            ReuseSpan          = reuseSpan;
        }
            public void AnalyzeCodeBlock(CodeBlockAnalysisContext context)
            {
                if (_analyzer.IsIgnoredCodeBlock(context.CodeBlock))
                {
                    return;
                }

                var(completed, intervalTree) = _codeBlockIntervals.GetOrAdd(context.CodeBlock.SyntaxTree, _ => (new StrongBox <bool>(false), SimpleIntervalTree.Create(new TextSpanIntervalIntrospector(), Array.Empty <TextSpan>())));
                if (completed.Value)
                {
                    return;
                }

                RoslynDebug.AssertNotNull(intervalTree);
                lock (completed)
                {
                    if (completed.Value)
                    {
                        return;
                    }

                    if (intervalTree.HasIntervalThatOverlapsWith(context.CodeBlock.FullSpan.Start, context.CodeBlock.FullSpan.End))
                    {
                        return;
                    }

                    intervalTree.AddIntervalInPlace(context.CodeBlock.FullSpan);
                }

                _analyzer.AnalyzeCodeBlock(context);
            }
Beispiel #5
0
        public void TestPreviewDiagnostic()
        {
            var hostServices = EditorTestCompositions.EditorFeatures.GetHostServices();

            var diagnosticService = (IDiagnosticUpdateSource)((IMefHostExportProvider)hostServices).GetExportedValue <IDiagnosticAnalyzerService>();

            RoslynDebug.AssertNotNull(diagnosticService);

            var taskSource = new TaskCompletionSource <DiagnosticsUpdatedArgs>();

            diagnosticService.DiagnosticsUpdated += (s, a) => taskSource.TrySetResult(a);

            using var previewWorkspace = new PreviewWorkspace(hostServices);

            var solution = previewWorkspace.CurrentSolution
                           .WithAnalyzerReferences(new[] { DiagnosticExtensions.GetCompilerDiagnosticAnalyzerReference(LanguageNames.CSharp) })
                           .AddProject("project", "project.dll", LanguageNames.CSharp)
                           .AddDocument("document", "class { }")
                           .Project
                           .Solution;

            Assert.True(previewWorkspace.TryApplyChanges(solution));

            previewWorkspace.OpenDocument(previewWorkspace.CurrentSolution.Projects.First().DocumentIds[0]);
            previewWorkspace.EnableDiagnostic();

            // wait 20 seconds
            taskSource.Task.Wait(20000);
            Assert.True(taskSource.Task.IsCompleted);

            var args = taskSource.Task.Result;

            Assert.True(args.Diagnostics.Length > 0);
        }
Beispiel #6
0
        private void ReportDiagnosticsIfNeeded(NameColonSyntax nameColon, SyntaxNodeAnalysisContext context, AnalyzerOptions options, SyntaxTree syntaxTree, CancellationToken cancellationToken)
        {
            if (!nameColon.Parent.IsKind(SyntaxKind.Argument, out ArgumentSyntax? argument))
            {
                return;
            }

            var parseOptions = (CSharpParseOptions)syntaxTree.Options;
            var preference   = options.GetOption(
                CodeStyleOptions.PreferInferredTupleNames, context.Compilation.Language, syntaxTree, cancellationToken);

            if (!preference.Value ||
                !CSharpInferredMemberNameReducer.CanSimplifyTupleElementName(argument, parseOptions))
            {
                return;
            }

            // Create a normal diagnostic
            context.ReportDiagnostic(
                DiagnosticHelper.Create(
                    Descriptor,
                    nameColon.GetLocation(),
                    preference.Notification.Severity,
                    additionalLocations: null,
                    properties: null));

            // Also fade out the part of the name-colon syntax
            RoslynDebug.AssertNotNull(UnnecessaryWithoutSuggestionDescriptor);
            var fadeSpan = TextSpan.FromBounds(nameColon.Name.SpanStart, nameColon.ColonToken.Span.End);

            context.ReportDiagnostic(
                Diagnostic.Create(
                    UnnecessaryWithoutSuggestionDescriptor,
                    syntaxTree.GetLocation(fadeSpan)));
        }
Beispiel #7
0
        private void TrackBulkFileOperations()
        {
            RoslynDebug.AssertNotNull(_workspace);

            // we will pause whatever ambient work loads we have that are tied to IGlobalOperationNotificationService
            // such as solution crawler, pre-emptive remote host synchronization and etc. any background work users didn't
            // explicitly asked for.
            //
            // this should give all resources to BulkFileOperation. we do same for things like build,
            // debugging, wait dialog and etc. BulkFileOperation is used for things like git branch switching and etc.
            var globalNotificationService = _workspace.Services.GetRequiredService <IGlobalOperationNotificationService>();

            // BulkFileOperation can't have nested events. there will be ever only 1 events (Begin/End)
            // so we only need simple tracking.
            var         gate = new object();
            IDisposable?localRegistration = null;

            BulkFileOperation.Begin += (s, a) => StartBulkFileOperationNotification();
            BulkFileOperation.End   += (s, a) => StopBulkFileOperationNotification();

            return;

            void StartBulkFileOperationNotification()
            {
                RoslynDebug.Assert(gate != null);
                RoslynDebug.Assert(globalNotificationService != null);

                lock (gate)
                {
                    // this shouldn't happen, but we are using external component
                    // so guarding us from them
                    if (localRegistration != null)
                    {
                        FatalError.ReportAndCatch(new InvalidOperationException("BulkFileOperation already exist"), ErrorSeverity.General);
                        return;
                    }

                    localRegistration = globalNotificationService.Start("BulkFileOperation");
                }
            }

            void StopBulkFileOperationNotification()
            {
                RoslynDebug.Assert(gate != null);

                lock (gate)
                {
                    // this can happen if BulkFileOperation was already in the middle
                    // of running. to make things simpler, decide to not use IsInProgress
                    // which we need to worry about race case.
                    if (localRegistration == null)
                    {
                        return;
                    }

                    localRegistration.Dispose();
                    localRegistration = null;
                }
            }
        }
Beispiel #8
0
        public override async Task InitializeAsync()
        {
            await base.InitializeAsync().ConfigureAwait(true);

            if (_solutionName != null)
            {
                RoslynDebug.AssertNotNull(_projectTemplate);

                await TestServices.SolutionExplorer.CreateSolutionAsync(_solutionName, HangMitigatingCancellationToken);

                await TestServices.SolutionExplorer.AddProjectAsync(ProjectName, _projectTemplate, LanguageName, HangMitigatingCancellationToken);

                await TestServices.SolutionExplorer.RestoreNuGetPackagesAsync(ProjectName, HangMitigatingCancellationToken);

                // Winforms and XAML do not open text files on creation
                // so these editor tasks will not work if that is the project template being used.
                if (_projectTemplate is not WellKnownProjectTemplates.WinFormsApplication and
                    not WellKnownProjectTemplates.WpfApplication and
                    not WellKnownProjectTemplates.CSharpNetCoreClassLibrary and
                    not WellKnownProjectTemplates.VisualBasicNetCoreClassLibrary)
                {
                    await TestServices.Editor.SetUseSuggestionModeAsync(false, HangMitigatingCancellationToken);
                    await ClearEditorAsync(HangMitigatingCancellationToken);
                }
            }
        }
Beispiel #9
0
            public static bool TryRead(string filterFilename, PathResolver pathResolver, [NotNullWhen(true)] out string?solutionFilename, out ImmutableHashSet <string> projectFilter)
            {
                try
                {
                    using var document = JsonDocument.Parse(File.ReadAllText(filterFilename));
                    var solution = document.RootElement.GetProperty("solution");
                    // Convert directory separators to the platform's default, since that is what MSBuild provide us.
                    var solutionPath = solution.GetProperty("path").GetString()?.Replace('\\', Path.DirectorySeparatorChar);
                    if (solutionPath is null || Path.GetDirectoryName(filterFilename) is not string baseDirectory)
                    {
                        solutionFilename = string.Empty;
                        projectFilter    = ImmutableHashSet <string> .Empty;
                        return(false);
                    }

                    if (!pathResolver.TryGetAbsoluteSolutionPath(solutionPath, baseDirectory, DiagnosticReportingMode.Throw, out solutionFilename))
                    {
                        // TryGetAbsoluteSolutionPath should throw before we get here.
                        solutionFilename = string.Empty;
                        projectFilter    = ImmutableHashSet <string> .Empty;
                        return(false);
                    }

                    if (!File.Exists(solutionFilename))
                    {
                        projectFilter = ImmutableHashSet <string> .Empty;
                        return(false);
                    }

                    // The base directory for projects is the solution folder.
                    baseDirectory = Path.GetDirectoryName(solutionFilename) !;
                    RoslynDebug.AssertNotNull(baseDirectory);

                    var filterProjects = ImmutableHashSet.CreateBuilder <string>(StringComparer.OrdinalIgnoreCase);
                    foreach (var project in solution.GetProperty("projects").EnumerateArray())
                    {
                        // Convert directory separators to the platform's default, since that is what MSBuild provide us.
                        var projectPath = project.GetString()?.Replace('\\', Path.DirectorySeparatorChar);
                        if (projectPath is null)
                        {
                            continue;
                        }

                        // Fill the filter with the absolute project paths.
                        if (pathResolver.TryGetAbsoluteProjectPath(projectPath, baseDirectory, DiagnosticReportingMode.Throw, out var absoluteProjectPath))
                        {
                            filterProjects.Add(absoluteProjectPath);
                        }
                    }

                    projectFilter = filterProjects.ToImmutable();
                    return(true);
                }
                catch
                {
                    solutionFilename = string.Empty;
                    projectFilter    = ImmutableHashSet <string> .Empty;
                    return(false);
                }
            }
Beispiel #10
0
        private static TypeSymbol DecodeTupleTypesInternal(TypeSymbol metadataType, ImmutableArray <string?> elementNames, bool hasTupleElementNamesAttribute)
        {
            RoslynDebug.AssertNotNull(metadataType);

            var decoder = new TupleTypeDecoder(elementNames);

            try
            {
                var decoded = decoder.DecodeType(metadataType);
                // If not all of the names have been used, the metadata is bad
                if (!hasTupleElementNamesAttribute ||
                    decoder._namesIndex == 0)
                {
                    return(decoded);
                }
            }
            catch (InvalidOperationException)
            {
                // Indicates that the tuple info in the attribute didn't match
                // the type. Bad metadata.
            }

            if (metadataType.HasUseSiteError)
            {
                return(metadataType);
            }

            // Bad metadata
            return(new UnsupportedMetadataTypeSymbol());
        }
Beispiel #11
0
        private static TypeSymbol DecodeTupleTypesInternal(
            TypeSymbol metadataType,
            ImmutableArray <string?> elementNames,
            bool hasTupleElementNamesAttribute
            )
        {
            RoslynDebug.AssertNotNull(metadataType);

            var decoder = new TupleTypeDecoder(elementNames);
            var decoded = decoder.DecodeType(metadataType);

            if (!decoder._decodingFailed)
            {
                if (!hasTupleElementNamesAttribute || decoder._namesIndex == 0)
                {
                    return(decoded);
                }
            }

            // If not all of the names have been used, the metadata is bad
            if (decoder._foundUsableErrorType)
            {
                return(metadataType);
            }

            // Bad metadata
            return(new UnsupportedMetadataTypeSymbol());
        }
Beispiel #12
0
        public void SerializeSourceText(
            SerializableSourceText text,
            ObjectWriter writer,
            SolutionReplicationContext context,
            CancellationToken cancellationToken
            )
        {
            cancellationToken.ThrowIfCancellationRequested();
            if (text.Storage is not null)
            {
                context.AddResource(text.Storage);

                writer.WriteInt32((int)text.Storage.ChecksumAlgorithm);
                writer.WriteEncoding(text.Storage.Encoding);

                writer.WriteInt32((int)SerializationKinds.MemoryMapFile);
                writer.WriteString(text.Storage.Name);
                writer.WriteInt64(text.Storage.Offset);
                writer.WriteInt64(text.Storage.Size);
            }
            else
            {
                RoslynDebug.AssertNotNull(text.Text);

                writer.WriteInt32((int)text.Text.ChecksumAlgorithm);
                writer.WriteEncoding(text.Text.Encoding);
                writer.WriteInt32((int)SerializationKinds.Bits);
                text.Text.WriteTo(writer, cancellationToken);
            }
        }
Beispiel #13
0
        internal sealed override void DecodeWellKnownAttribute(ref DecodeWellKnownAttributeArguments <AttributeSyntax, CSharpAttributeData, AttributeLocation> arguments)
        {
            var attribute = arguments.Attribute;

            Debug.Assert(!attribute.HasErrors);
            Debug.Assert(arguments.SymbolPart == AttributeLocation.None);

            if (attribute.IsTargetAttribute(this, AttributeDescription.SpecialNameAttribute))
            {
                arguments.GetOrCreateData <CommonEventWellKnownAttributeData>().HasSpecialNameAttribute = true;
            }
            else if (attribute.IsTargetAttribute(this, AttributeDescription.NullableAttribute))
            {
                // NullableAttribute should not be set explicitly.
                RoslynDebug.AssertNotNull(arguments.AttributeSyntaxOpt);
                arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitNullableAttribute, arguments.AttributeSyntaxOpt.Location);
            }
            else if (attribute.IsTargetAttribute(this, AttributeDescription.ExcludeFromCodeCoverageAttribute))
            {
                arguments.GetOrCreateData <CommonEventWellKnownAttributeData>().HasExcludeFromCodeCoverageAttribute = true;
            }
            else if (attribute.IsTargetAttribute(this, AttributeDescription.TupleElementNamesAttribute))
            {
                RoslynDebug.AssertNotNull(arguments.AttributeSyntaxOpt);
                arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitTupleElementNamesAttribute, arguments.AttributeSyntaxOpt.Location);
            }
            else if (attribute.IsTargetAttribute(this, AttributeDescription.SkipLocalsInitAttribute))
            {
                CSharpAttributeData.DecodeSkipLocalsInitAttribute <CommonEventWellKnownAttributeData>(DeclaringCompilation, ref arguments);
            }
        }
Beispiel #14
0
            private void OnWorkspaceChanged(object?sender, WorkspaceChangeEventArgs e)
            {
                if (e.Kind == WorkspaceChangeKind.ProjectChanged)
                {
                    RoslynDebug.AssertNotNull(e.ProjectId);
                    var oldProject = e.OldSolution.GetRequiredProject(e.ProjectId);
                    var newProject = e.NewSolution.GetRequiredProject(e.ProjectId);

                    if (!object.Equals(oldProject.ParseOptions, newProject.ParseOptions))
                    {
                        var workspace  = e.NewSolution.Workspace;
                        var documentId = workspace.GetDocumentIdInCurrentContext(
                            SubjectBuffer.AsTextContainer()
                            );
                        if (documentId != null)
                        {
                            var relatedDocumentIds = e.NewSolution.GetRelatedDocumentIds(
                                documentId
                                );

                            if (relatedDocumentIds.Any(d => d.ProjectId == e.ProjectId))
                            {
                                RaiseChanged();
                            }
                        }
                    }
                }
            }
Beispiel #15
0
        protected void AddBraceSuppressOperations(List <SuppressOperation> list, SyntaxNode node)
        {
            var bracePair = node.GetBracePair();

            if (!bracePair.IsValidBracePair())
            {
                return;
            }

            var firstTokenOfNode = node.GetFirstToken(includeZeroWidth: true);

            if (node is MemberDeclarationSyntax memberDeclNode)
            {
                (firstTokenOfNode, _) = memberDeclNode.GetFirstAndLastMemberDeclarationTokensAfterAttributes();
            }

            if (node.IsLambdaBodyBlock())
            {
                RoslynDebug.AssertNotNull(node.Parent);

                // include lambda itself.
                firstTokenOfNode = node.Parent.GetFirstToken(includeZeroWidth: true);
            }
            else if (node.IsKind(SyntaxKind.PropertyPatternClause))
            {
                // include the pattern recursive pattern syntax and/or subpattern
                firstTokenOfNode = firstTokenOfNode.GetPreviousToken();
            }

            // suppress wrapping on whole construct that owns braces and also brace pair itself if
            // it is on same line
            AddSuppressWrappingIfOnSingleLineOperation(list, firstTokenOfNode, bracePair.closeBrace);
            AddSuppressWrappingIfOnSingleLineOperation(list, bracePair.openBrace, bracePair.closeBrace);
        }
Beispiel #16
0
            public void CompleteFromTask(Task <T> task)
            {
                // As an optimization, we'll cancel the request even we did get a value for it.
                // That way things abort sooner.
                if (task.IsCanceled || _cancellationToken.IsCancellationRequested)
                {
                    Cancel();
                }
                else if (task.IsFaulted)
                {
                    // TrySetException wraps its argument in an AggregateException, so we pass the inner exceptions from
                    // the antecedent to avoid wrapping in two layers of AggregateException.
                    RoslynDebug.AssertNotNull(task.Exception);
                    if (task.Exception.InnerExceptions.Count > 0)
                    {
                        this.TrySetException(task.Exception.InnerExceptions);
                    }
                    else
                    {
                        this.TrySetException(task.Exception);
                    }
                }
                else
                {
                    this.TrySetResult(task.Result);
                }

                _cancellationTokenRegistration.Dispose();
            }
        private static SyntaxNode?GetTopContainingNode([DisallowNull] SyntaxNode?node)
        {
            RoslynDebug.AssertNotNull(node.Parent);

            node = node.Parent;
            if (!IsSpecialContainingNode(node))
            {
                return(node);
            }

            var lastSpecialContainingNode = node;

            node = node.Parent;

            while (node != null)
            {
                if (!IsSpecialContainingNode(node))
                {
                    return(lastSpecialContainingNode);
                }

                lastSpecialContainingNode = node;
                node = node.Parent;
            }

            return(null);
        }
        private static async Task <Solution> FixAllInDocumentAsync(Document document, ImmutableArray <Diagnostic> diagnostics, CodeActionOptionsProvider options, CancellationToken cancellationToken)
        {
            // All the target namespaces should be the same for a given document
            Debug.Assert(diagnostics.Select(diagnostic => diagnostic.Properties[MatchFolderAndNamespaceConstants.TargetNamespace]).Distinct().Count() == 1);

            var targetNamespace = diagnostics.First().Properties[MatchFolderAndNamespaceConstants.TargetNamespace];

            RoslynDebug.AssertNotNull(targetNamespace);

            // Use the Renamer.RenameDocumentAsync API to sync namespaces in the document. This allows
            // us to keep in line with the sync methodology that we have as a public API and not have
            // to rewrite or move the complex logic. RenameDocumentAsync is designed to behave the same
            // as the intent of this analyzer/codefix pair.
            var targetFolders = PathMetadataUtilities.BuildFoldersFromNamespace(targetNamespace, document.Project.DefaultNamespace);
            var documentWithInvalidFolders = document.WithFolders(document.Folders.Concat("Force-Namespace-Change"));
            var renameActionSet            = await Renamer.RenameDocumentAsync(
                documentWithInvalidFolders,
                new DocumentRenameOptions(),
#if !CODE_STYLE
                options,
#endif
                documentWithInvalidFolders.Name,
                newDocumentFolders : targetFolders,
                cancellationToken : cancellationToken).ConfigureAwait(false);

            var newSolution = await renameActionSet.UpdateSolutionAsync(documentWithInvalidFolders.Project.Solution, cancellationToken).ConfigureAwait(false);

            Debug.Assert(newSolution != document.Project.Solution);
            return(newSolution);
        }
Beispiel #19
0
        private void ReportDiagnosticsIfNeeded(NameEqualsSyntax nameEquals, SyntaxNodeAnalysisContext context, AnalyzerOptions options, SyntaxTree syntaxTree, CancellationToken cancellationToken)
        {
            if (!nameEquals.Parent.IsKind(SyntaxKind.AnonymousObjectMemberDeclarator, out AnonymousObjectMemberDeclaratorSyntax? anonCtor))
            {
                return;
            }

            var preference = options.GetOption(
                CodeStyleOptions.PreferInferredAnonymousTypeMemberNames, context.Compilation.Language, syntaxTree, cancellationToken);

            if (!preference.Value ||
                !CSharpInferredMemberNameReducer.CanSimplifyAnonymousTypeMemberName(anonCtor))
            {
                return;
            }

            // Create a normal diagnostic
            context.ReportDiagnostic(
                DiagnosticHelper.Create(
                    Descriptor,
                    nameEquals.GetLocation(),
                    preference.Notification.Severity,
                    additionalLocations: null,
                    properties: null));

            // Also fade out the part of the name-equals syntax
            RoslynDebug.AssertNotNull(UnnecessaryWithoutSuggestionDescriptor);
            var fadeSpan = TextSpan.FromBounds(nameEquals.Name.SpanStart, nameEquals.EqualsToken.Span.End);

            context.ReportDiagnostic(
                Diagnostic.Create(
                    UnnecessaryWithoutSuggestionDescriptor,
                    syntaxTree.GetLocation(fadeSpan)));
        }
        /// <summary>
        /// Construct a body for a method containing a call to a single other method with the same signature (modulo name).
        /// </summary>
        /// <param name="F">Bound node factory.</param>
        /// <param name="methodToInvoke">Method to invoke in constructed body.</param>
        /// <param name="useBaseReference">True for "base.", false for "this.".</param>
        /// <returns>Body for implementedMethod.</returns>
        internal static BoundBlock ConstructSingleInvocationMethodBody(
            SyntheticBoundNodeFactory F,
            MethodSymbol methodToInvoke,
            bool useBaseReference
            )
        {
            var argBuilder = ArrayBuilder <BoundExpression> .GetInstance();

            RoslynDebug.AssertNotNull(F.CurrentFunction);
            foreach (var param in F.CurrentFunction.Parameters)
            {
                argBuilder.Add(F.Parameter(param));
            }

            BoundExpression invocation = F.Call(
                useBaseReference
                  ? (BoundExpression)F.Base(baseType: methodToInvoke.ContainingType)
                  : F.This(),
                methodToInvoke,
                argBuilder.ToImmutableAndFree()
                );

            return(F.CurrentFunction.ReturnsVoid
              ? F.Block(F.ExpressionStatement(invocation), F.Return())
              : F.Block(F.Return(invocation)));
        }
Beispiel #21
0
        public DirectiveStack Add(Directive directive)
        {
            switch (directive.Kind)
            {
            case SyntaxKind.EndIfDirectiveTrivia:
                var prevIf = GetPreviousIf(_directives);
                if (prevIf == null || !prevIf.Any())
                {
                    goto default;     // no matching if directive !! leave directive alone
                }

                RoslynDebug.AssertNotNull(_directives);     // If 'prevIf' isn't null, then '_directives' wasn't null.
                return(new DirectiveStack(CompleteIf(_directives, out _)));

            case SyntaxKind.EndRegionDirectiveTrivia:
                var prevRegion = GetPreviousRegion(_directives);
                if (prevRegion == null || !prevRegion.Any())
                {
                    goto default;     // no matching region directive !! leave directive alone
                }

                RoslynDebug.AssertNotNull(_directives);                  // If 'prevRegion' isn't null, then '_directives' wasn't null.
                return(new DirectiveStack(CompleteRegion(_directives))); // remove region directives from stack but leave everything else

            default:
                return(new DirectiveStack(new ConsList <Directive>(directive, _directives ?? ConsList <Directive> .Empty)));
            }
        }
Beispiel #22
0
        /// <returns>The tracking span of the inserted "/**/" if there is an $end$ location, null
        /// otherwise.</returns>
        protected override ITrackingSpan?InsertEmptyCommentAndGetEndPositionTrackingSpan()
        {
            RoslynDebug.AssertNotNull(ExpansionSession);

            var endSpanInSurfaceBuffer = new VsTextSpan[1];

            if (ExpansionSession.GetEndSpan(endSpanInSurfaceBuffer) != VSConstants.S_OK)
            {
                return(null);
            }

            if (!TryGetSubjectBufferSpan(endSpanInSurfaceBuffer[0], out var subjectBufferEndSpan))
            {
                return(null);
            }

            var endPosition = subjectBufferEndSpan.Start.Position;

            var commentString = "/**/";

            SubjectBuffer.Insert(endPosition, commentString);

            var commentSpan = new Span(endPosition, commentString.Length);

            return(SubjectBuffer.CurrentSnapshot.CreateTrackingSpan(commentSpan, SpanTrackingMode.EdgeExclusive));
        }
Beispiel #23
0
        /// <inheritdoc/>
        public async Task <Solution> SyncNamespacesAsync(
            ImmutableArray <Project> projects,
            CodeActionOptionsProvider options,
            CancellationToken cancellationToken)
        {
            // all projects must be of the same language
            Debug.Assert(projects.All(project => project.Language == projects[0].Language));

            var solution             = projects[0].Solution;
            var diagnosticAnalyzers  = ImmutableArray.Create <DiagnosticAnalyzer>(DiagnosticAnalyzer);
            var diagnosticsByProject = await GetDiagnosticsByProjectAsync(projects, diagnosticAnalyzers, cancellationToken).ConfigureAwait(false);

            // If no diagnostics are reported, then there is nothing to fix.
            if (diagnosticsByProject.Values.All(diagnostics => diagnostics.IsEmpty))
            {
                return(solution);
            }

            var fixAllContext = await GetFixAllContextAsync(solution, CodeFixProvider, diagnosticsByProject, options, cancellationToken).ConfigureAwait(false);

            var fixAllProvider = CodeFixProvider.GetFixAllProvider();

            RoslynDebug.AssertNotNull(fixAllProvider);

            return(await ApplyCodeFixAsync(fixAllProvider, fixAllContext, cancellationToken).ConfigureAwait(false));
        }
        public async Task TestGlobalImports()
        {
            // Make sure no glyph is in the margin at first.
            await TestServices.InheritanceMargin.DisableOptionsAsync(LanguageName, HangMitigatingCancellationToken);

            await TestServices.SolutionExplorer.OpenFileAsync(
                ProjectName, "Class1.cs", HangMitigatingCancellationToken);

            await TestServices.InheritanceMargin.EnableOptionsAndEnsureGlyphsAppearAsync(LanguageName, 1, HangMitigatingCancellationToken);

            await TestServices.InheritanceMargin.ClickTheGlyphOnLine(1, HangMitigatingCancellationToken);

            // Move focus to menu item 'System'
            await TestServices.Input.SendWithoutActivateAsync(VirtualKeyCode.TAB);

            // Navigate to 'System'
            await TestServices.Input.SendWithoutActivateAsync(VirtualKeyCode.RETURN);

            await TestServices.Workspace.WaitForAllAsyncOperationsAsync(new[] { FeatureAttribute.InheritanceMargin }, HangMitigatingCancellationToken);

            await TestServices.EditorVerifier.TextContainsAsync(@"global using global::System;$$", assertCaretPosition : true);

            var document = await TestServices.Editor.GetActiveDocumentAsync(HangMitigatingCancellationToken);

            RoslynDebug.AssertNotNull(document);
            Assert.NotEqual(WorkspaceKind.MetadataAsSource, document.Project.Solution.Workspace.Kind);
        }
Beispiel #25
0
        public override BoundNode VisitWithExpression(BoundWithExpression withExpr)
        {
            RoslynDebug.AssertNotNull(withExpr.CloneMethod);
            Debug.Assert(withExpr.CloneMethod.ParameterCount == 0);
            Debug.Assert(withExpr.Receiver.Type !.Equals(withExpr.Type, TypeCompareKind.ConsiderEverything));

            // for a with expression of the form
            //
            //      receiver with { P1 = e1, P2 = e2 }
            //
            // we want to lower it to a call to the receiver's `Clone` method, then
            // set the given record properties. i.e.
            //
            //      var tmp = (ReceiverType)receiver.Clone();
            //      tmp.P1 = e1;
            //      tmp.P2 = e2;
            //      tmp

            var cloneCall = _factory.Convert(
                withExpr.Type,
                _factory.Call(
                    VisitExpression(withExpr.Receiver),
                    withExpr.CloneMethod));

            return(MakeExpressionWithInitializer(
                       withExpr.Syntax,
                       cloneCall,
                       withExpr.InitializerExpression,
                       withExpr.Type));
        }
Beispiel #26
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ImmutableHashMap&lt;TKey, TValue&gt;.ListBucket"/> class.
 /// </summary>
 /// <param name="buckets">The buckets.</param>
 internal ListBucket(ValueBucket[] buckets)
     : base(buckets[0].Hash)
 {
     RoslynDebug.AssertNotNull(buckets);
     Debug.Assert(buckets.Length >= 2);
     _buckets = buckets;
 }
Beispiel #27
0
        private async Task <Document> CleanupCoreAsync(
            Document document,
            ImmutableArray <TextSpan> spans,
            CancellationToken cancellationToken
            )
        {
            RoslynDebug.AssertNotNull(_syntaxDelegatee);

            var root = await document
                       .GetRequiredSyntaxRootAsync(cancellationToken)
                       .ConfigureAwait(false);

            var newRoot = _syntaxDelegatee(
                root,
                spans,
                document.Project.Solution.Workspace,
                cancellationToken
                );

            if (root != newRoot)
            {
                return(document.WithSyntaxRoot(newRoot));
            }

            return(document);
        }
Beispiel #28
0
            /// <summary>
            /// Initializes a new instance of the <see cref="ImmutableHashMap&lt;TKey, TValue&gt;.HashBucket"/> class.
            /// </summary>
            /// <param name="suggestedHashRoll">The suggested hash roll.</param>
            /// <param name="bucket1">The bucket1.</param>
            /// <param name="bucket2">The bucket2.</param>
            internal HashBucket(int suggestedHashRoll, ValueOrListBucket bucket1, ValueOrListBucket bucket2)
            {
                RoslynDebug.AssertNotNull(bucket1);
                RoslynDebug.AssertNotNull(bucket2);
                Debug.Assert(bucket1.Hash != bucket2.Hash);

                // find next hashRoll that causes these two to be slotted in different buckets
                var h1 = bucket1.Hash;
                var h2 = bucket2.Hash;
                int s1;
                int s2;

                for (var i = 0; i < 32; i++)
                {
                    _hashRoll = (suggestedHashRoll + i) & 31;
                    s1        = this.ComputeLogicalSlot(h1);
                    s2        = this.ComputeLogicalSlot(h2);
                    if (s1 != s2)
                    {
                        _count   = 2;
                        _used    = (1u << s1) | (1u << s2);
                        _buckets = new Bucket[2];
                        _buckets[this.ComputePhysicalSlot(s1)] = bucket1;
                        _buckets[this.ComputePhysicalSlot(s2)] = bucket2;
                        return;
                    }
                }

                throw new InvalidOperationException();
            }
Beispiel #29
0
        protected static void ValidateAndReportDiagnostic(
            SyntaxNodeAnalysisContext context,
            int numberOfPlaceholderArguments,
            string formatString,
            int formatStringPosition)
        {
            // removing escaped left brackets and replacing with space characters so they won't
            // impede the extraction of placeholders, yet the locations of the placeholders are
            // the same as in the original string.
            var formatStringWithEscapedBracketsChangedToSpaces = RemoveEscapedBrackets(formatString);

            var matches = s_extractPlaceholdersRegex.Matches(formatStringWithEscapedBracketsChangedToSpaces);

            foreach (Match?match in matches)
            {
                RoslynDebug.AssertNotNull(match);

                var textInsideBrackets = match.Groups[1].Value;

                if (!PlaceholderIndexIsValid(textInsideBrackets, numberOfPlaceholderArguments))
                {
                    var invalidPlaceholderText     = "{" + textInsideBrackets + "}";
                    var invalidPlaceholderLocation = Location.Create(
                        context.Node.SyntaxTree,
                        new Text.TextSpan(
                            formatStringPosition + match.Index,
                            invalidPlaceholderText.Length));
                    var diagnostic = Diagnostic.Create(
                        Rule,
                        invalidPlaceholderLocation,
                        invalidPlaceholderText);
                    context.ReportDiagnostic(diagnostic);
                }
            }
        }
Beispiel #30
0
        /// <summary>
        /// Calculate the set of changes up to top-level types. The result
        /// will be used as a filter when traversing the module.
        ///
        /// Note that these changes only include user-defined source symbols, not synthesized symbols since those will be
        /// generated during lowering of the changed user-defined symbols.
        /// </summary>
        private static void CalculateChanges(IEnumerable <SemanticEdit> edits, out IReadOnlyDictionary <ISymbol, SymbolChange> changes, out ISet <ISymbol> replaceSymbols)
        {
            var changesBuilder = new Dictionary <ISymbol, SymbolChange>();
            HashSet <ISymbol>?lazyReplaceSymbolsBuilder = null;

            foreach (var edit in edits)
            {
                SymbolChange change;

                switch (edit.Kind)
                {
                case SemanticEditKind.Update:
                    change = SymbolChange.Updated;
                    break;

                case SemanticEditKind.Insert:
                    change = SymbolChange.Added;
                    break;

                case SemanticEditKind.Replace:
                    Debug.Assert(edit.NewSymbol != null);
                    (lazyReplaceSymbolsBuilder ??= new HashSet <ISymbol>()).Add(edit.NewSymbol);
                    change = SymbolChange.Added;
                    break;

                case SemanticEditKind.Delete:
                    // No work to do.
                    continue;

                default:
                    throw ExceptionUtilities.UnexpectedValue(edit.Kind);
                }

                var member = edit.NewSymbol;
                RoslynDebug.AssertNotNull(member);

                // Partial methods are supplied as implementations but recorded
                // internally as definitions since definitions are used in emit.
                if (member.Kind == SymbolKind.Method)
                {
                    var method = (IMethodSymbol)member;

                    // Partial methods should be implementations, not definitions.
                    Debug.Assert(method.PartialImplementationPart == null);
                    Debug.Assert((edit.OldSymbol == null) || (((IMethodSymbol)edit.OldSymbol).PartialImplementationPart == null));

                    var definitionPart = method.PartialDefinitionPart;
                    if (definitionPart != null)
                    {
                        member = definitionPart;
                    }
                }

                AddContainingTypesAndNamespaces(changesBuilder, member);
                changesBuilder.Add(member, change);
            }

            changes        = changesBuilder;
            replaceSymbols = lazyReplaceSymbolsBuilder ?? SpecializedCollections.EmptySet <ISymbol>();
        }