private static ImmutableHashSet <string> GetAliasedNames(
            CompilationUnitSyntax?compilationUnit
            )
        {
            var aliasedNames = s_emptyAliasedNames;

            if (compilationUnit is null)
            {
                return(aliasedNames);
            }

            foreach (var usingDirective in compilationUnit.Usings)
            {
                AddAliasedName(usingDirective);
            }

            foreach (var member in compilationUnit.Members)
            {
                if (member is NamespaceDeclarationSyntax namespaceDeclaration)
                {
                    AddAliasedNames(namespaceDeclaration);
                }
            }

            return(aliasedNames);

            void AddAliasedName(UsingDirectiveSyntax usingDirective)
            {
                if (usingDirective.Alias is object)
                {
                    if (
                        usingDirective.Name.GetRightmostName()
                        is IdentifierNameSyntax identifierName
                        )
                    {
                        var identifierAlias = identifierName.Identifier.ValueText;
                        if (!RoslynString.IsNullOrEmpty(identifierAlias))
                        {
                            aliasedNames = aliasedNames.Add(identifierAlias);
                        }
                    }
                }
            }

            void AddAliasedNames(NamespaceDeclarationSyntax namespaceDeclaration)
            {
                foreach (var usingDirective in namespaceDeclaration.Usings)
                {
                    AddAliasedName(usingDirective);
                }

                foreach (var member in namespaceDeclaration.Members)
                {
                    if (member is NamespaceDeclarationSyntax memberNamespace)
                    {
                        AddAliasedNames(memberNamespace);
                    }
                }
            }
        }
Exemple #2
0
 private static void ValidateName(string name)
 {
     if (RoslynString.IsNullOrEmpty(name) || name.Contains(char.IsWhiteSpace))
     {
         throw new ArgumentException(WorkspaceMSBuildResources.Parameter_cannot_be_null_empty_or_contain_whitespace, nameof(name));
     }
 }
Exemple #3
0
        internal static bool TryParseUInt16(string?value, out ushort result)
        {
            result = 0;

            if (RoslynString.IsNullOrEmpty(value))
            {
                return(false);
            }

            int numBase = 10;

            if (value.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
            {
                numBase = 16;
            }
            else if (value.StartsWith("0", StringComparison.OrdinalIgnoreCase))
            {
                numBase = 8;
            }

            try
            {
                result = Convert.ToUInt16(value, numBase);
            }
            catch
            {
                return(false);
            }

            return(true);
        }
Exemple #4
0
        protected static string GetDocumentLogicalPath(
            MSB.Framework.ITaskItem documentItem,
            string projectDirectory
            )
        {
            var link = documentItem.GetMetadata(MetadataNames.Link);

            if (!RoslynString.IsNullOrEmpty(link))
            {
                // if a specific link is specified in the project file then use it to form the logical path.
                return(link);
            }
            else
            {
                var filePath = documentItem.ItemSpec;

                if (!PathUtilities.IsAbsolute(filePath))
                {
                    return(filePath);
                }

                var normalizedPath = FileUtilities.TryNormalizeAbsolutePath(filePath);
                if (normalizedPath == null)
                {
                    return(filePath);
                }

                // If the document is within the current project directory (or subdirectory), then the logical path is the relative path
                // from the project's directory.
                if (normalizedPath.StartsWith(projectDirectory, StringComparison.OrdinalIgnoreCase))
                {
                    return(normalizedPath[projectDirectory.Length..]);
        private void WriteRules()
        {
            if (_descriptors.Count > 0)
            {
                _writer.WriteObjectStart("rules");

                foreach (var pair in _descriptors.ToSortedList())
                {
                    DiagnosticDescriptor descriptor = pair.Value;

                    _writer.WriteObjectStart(pair.Key); // rule
                    _writer.Write("id", descriptor.Id);

                    string?shortDescription = descriptor.Title.ToString(_culture);
                    if (!RoslynString.IsNullOrEmpty(shortDescription))
                    {
                        _writer.Write("shortDescription", shortDescription);
                    }

                    string?fullDescription = descriptor.Description.ToString(_culture);
                    if (!RoslynString.IsNullOrEmpty(fullDescription))
                    {
                        _writer.Write("fullDescription", fullDescription);
                    }

                    _writer.Write("defaultLevel", GetLevel(descriptor.DefaultSeverity));

                    if (!string.IsNullOrEmpty(descriptor.HelpLinkUri))
                    {
                        _writer.Write("helpUri", descriptor.HelpLinkUri);
                    }

                    _writer.WriteObjectStart("properties");

                    if (!string.IsNullOrEmpty(descriptor.Category))
                    {
                        _writer.Write("category", descriptor.Category);
                    }

                    _writer.Write("isEnabledByDefault", descriptor.IsEnabledByDefault);

                    if (descriptor.CustomTags.Any())
                    {
                        _writer.WriteArrayStart("tags");

                        foreach (string tag in descriptor.CustomTags)
                        {
                            _writer.Write(tag);
                        }

                        _writer.WriteArrayEnd(); // tags
                    }

                    _writer.WriteObjectEnd(); // properties
                    _writer.WriteObjectEnd(); // rule
                }

                _writer.WriteObjectEnd(); // rules
            }
        }
Exemple #6
0
        internal Task <ImmutableDictionary <string, string> > GetAnalyzerOptionsAsync(CancellationToken cancellationToken)
        {
            var projectFilePath = Project.FilePath;
            // We need to work out path to this document. Documents may not have a "real" file path if they're something created
            // as a part of a code action, but haven't been written to disk yet.
            string?effectiveFilePath = null;

            if (FilePath != null)
            {
                effectiveFilePath = FilePath;
            }
            else if (Name != null && projectFilePath != null)
            {
                var projectPath = PathUtilities.GetDirectoryName(projectFilePath);

                if (!RoslynString.IsNullOrEmpty(projectPath) &&
                    PathUtilities.GetDirectoryName(projectFilePath) is string directory)
                {
                    effectiveFilePath = PathUtilities.CombinePathsUnchecked(directory, Name);
                }
            }

            if (effectiveFilePath != null)
            {
                return(Project.State.GetAnalyzerOptionsForPathAsync(effectiveFilePath, cancellationToken));
            }
            else
            {
                // Really no idea where this is going, so bail
                return(Task.FromResult(DictionaryAnalyzerConfigOptions.EmptyDictionary));
            }
        }
        public override void LogDiagnostic(Diagnostic diagnostic, SuppressionInfo?suppressionInfo)
        {
            _writer.WriteObjectStart(); // result
            _writer.Write("ruleId", diagnostic.Id);

            string ruleKey = _descriptors.Add(diagnostic.Descriptor);

            if (ruleKey != diagnostic.Id)
            {
                _writer.Write("ruleKey", ruleKey);
            }

            _writer.Write("level", GetLevel(diagnostic.Severity));

            string?message = diagnostic.GetMessage(_culture);

            if (!RoslynString.IsNullOrEmpty(message))
            {
                _writer.Write("message", message);
            }

            if (diagnostic.IsSuppressed)
            {
                _writer.WriteArrayStart("suppressionStates");
                _writer.Write("suppressedInSource");
                _writer.WriteArrayEnd();
            }

            WriteLocations(diagnostic.Location, diagnostic.AdditionalLocations);
            WriteResultProperties(diagnostic);

            _writer.WriteObjectEnd(); // result
        }
Exemple #8
0
            public static FixedLocalizableString Create(string?fixedResource)
            {
                if (RoslynString.IsNullOrEmpty(fixedResource))
                {
                    return(s_empty);
                }

                return(new FixedLocalizableString(fixedResource));
            }
Exemple #9
0
        /// <returns>
        /// <list type="bullet">
        /// <item><description><see langword="true"/> if <paramref name="applyFix"/> is specified and the fix is successfully applied</description></item>
        /// <item><description><see langword="false"/> if <paramref name="applyFix"/> is specified but the fix is not successfully applied</description></item>
        /// <item><description><see langword="null"/> if <paramref name="applyFix"/> is false, so there is no fix to apply</description></item>
        /// </list>
        /// </returns>
        public async Task <bool?> CodeActionsAsync(
            IEnumerable <string> expectedItems,
            string?applyFix       = null,
            bool verifyNotShowing = false,
            bool ensureExpectedItemsAreOrdered  = false,
            FixAllScope?fixAllScope             = null,
            bool blockUntilComplete             = true,
            CancellationToken cancellationToken = default)
        {
            await TestServices.Editor.ShowLightBulbAsync(cancellationToken);

            if (verifyNotShowing)
            {
                await CodeActionsNotShowingAsync(cancellationToken);

                return(null);
            }

            var actions = await TestServices.Editor.GetLightBulbActionsAsync(cancellationToken);

            if (expectedItems != null && expectedItems.Any())
            {
                if (ensureExpectedItemsAreOrdered)
                {
                    TestUtilities.ThrowIfExpectedItemNotFoundInOrder(
                        actions,
                        expectedItems);
                }
                else
                {
                    TestUtilities.ThrowIfExpectedItemNotFound(
                        actions,
                        expectedItems);
                }
            }

            if (fixAllScope.HasValue)
            {
                Assumes.Present(applyFix);
            }

            if (!RoslynString.IsNullOrEmpty(applyFix))
            {
                var result = await TestServices.Editor.ApplyLightBulbActionAsync(applyFix, fixAllScope, blockUntilComplete, cancellationToken);

                if (blockUntilComplete)
                {
                    // wait for action to complete
                    await TestServices.Workspace.WaitForAsyncOperationsAsync(FeatureAttribute.LightBulb, cancellationToken);
                }

                return(result);
            }

            return(null);
        }
Exemple #10
0
            /// <returns>
            /// <list type="bullet">
            /// <item><description><see langword="true"/> if <paramref name="applyFix"/> is specified and the fix is successfully applied</description></item>
            /// <item><description><see langword="false"/> if <paramref name="applyFix"/> is specified but the fix is not successfully applied</description></item>
            /// <item><description><see langword="null"/> if <paramref name="applyFix"/> is false, so there is no fix to apply</description></item>
            /// </list>
            /// </returns>
            public bool?CodeActions(
                IEnumerable <string> expectedItems,
                string?applyFix       = null,
                bool verifyNotShowing = false,
                bool ensureExpectedItemsAreOrdered = false,
                FixAllScope?fixAllScope            = null,
                bool blockUntilComplete            = true)
            {
                _textViewWindow.ShowLightBulb();
                _textViewWindow.WaitForLightBulbSession();

                if (verifyNotShowing)
                {
                    CodeActionsNotShowing();
                    return(null);
                }

                var actions = _textViewWindow.GetLightBulbActions();

                if (expectedItems != null && expectedItems.Any())
                {
                    if (ensureExpectedItemsAreOrdered)
                    {
                        TestUtilities.ThrowIfExpectedItemNotFoundInOrder(
                            actions,
                            expectedItems);
                    }
                    else
                    {
                        TestUtilities.ThrowIfExpectedItemNotFound(
                            actions,
                            expectedItems);
                    }
                }

                if (fixAllScope.HasValue)
                {
                    Contract.ThrowIfNull(applyFix);
                }

                if (!RoslynString.IsNullOrEmpty(applyFix))
                {
                    var result = _textViewWindow.ApplyLightBulbAction(applyFix, fixAllScope, blockUntilComplete);

                    if (blockUntilComplete)
                    {
                        // wait for action to complete
                        _instance.Workspace.WaitForAsyncOperations(Helper.HangMitigatingTimeout, FeatureAttribute.LightBulb);
                    }

                    return(result);
                }

                return(null);
            }
Exemple #11
0
        public async Task <ImmutableArray <ProjectFileInfo> > GetProjectFileInfosAsync(CancellationToken cancellationToken)
        {
            if (_loadedProject is null)
            {
                return(ImmutableArray.Create(ProjectFileInfo.CreateEmpty(Language, _loadedProject?.FullPath, Log)));
            }

            var targetFrameworkValue  = _loadedProject.GetPropertyValue(PropertyNames.TargetFramework);
            var targetFrameworksValue = _loadedProject.GetPropertyValue(PropertyNames.TargetFrameworks);

            if (RoslynString.IsNullOrEmpty(targetFrameworkValue) && !RoslynString.IsNullOrEmpty(targetFrameworksValue))
            {
                // This project has a <TargetFrameworks> property, but does not specify a <TargetFramework>.
                // In this case, we need to iterate through the <TargetFrameworks>, set <TargetFramework> with
                // each value, and build the project.

                var targetFrameworks = targetFrameworksValue.Split(';');
                var results          = ImmutableArray.CreateBuilder <ProjectFileInfo>(targetFrameworks.Length);

                if (!_loadedProject.GlobalProperties.TryGetValue(PropertyNames.TargetFramework, out var initialGlobalTargetFrameworkValue))
                {
                    initialGlobalTargetFrameworkValue = null;
                }

                foreach (var targetFramework in targetFrameworks)
                {
                    _loadedProject.SetGlobalProperty(PropertyNames.TargetFramework, targetFramework);
                    _loadedProject.ReevaluateIfNecessary();

                    var projectFileInfo = await BuildProjectFileInfoAsync(cancellationToken).ConfigureAwait(false);

                    results.Add(projectFileInfo);
                }

                if (initialGlobalTargetFrameworkValue is null)
                {
                    _loadedProject.RemoveGlobalProperty(PropertyNames.TargetFramework);
                }
                else
                {
                    _loadedProject.SetGlobalProperty(PropertyNames.TargetFramework, initialGlobalTargetFrameworkValue);
                }

                _loadedProject.ReevaluateIfNecessary();

                return(results.ToImmutable());
            }
            else
            {
                var projectFileInfo = await BuildProjectFileInfoAsync(cancellationToken).ConfigureAwait(false);

                projectFileInfo ??= ProjectFileInfo.CreateEmpty(Language, _loadedProject?.FullPath, Log);
                return(ImmutableArray.Create(projectFileInfo));
            }
        }
Exemple #12
0
        /// <summary>
        /// Adds a "/features:" switch to the command line for each provided feature.
        /// </summary>
        internal static void AddFeatures(CommandLineBuilderExtension commandLine, string?features)
        {
            if (RoslynString.IsNullOrEmpty(features))
            {
                return;
            }

            foreach (var feature in CompilerOptionParseUtilities.ParseFeatureFromMSBuild(features))
            {
                commandLine.AppendSwitchIfNotNull("/features:", feature.Trim());
            }
        }
Exemple #13
0
        protected void Add(string name, string?value)
        {
            ValidateName(name);

            if (RoslynString.IsNullOrEmpty(value) || value.Contains(char.IsWhiteSpace))
            {
                _builder.Add($"/{name}:\"{value}\"");
            }
            else
            {
                _builder.Add($"/{name}:{value}");
            }
        }
Exemple #14
0
        public LocalConstantDefinition(
            string name,
            Location location,
            MetadataConstant compileTimeValue,
            ImmutableArray <bool> dynamicTransformFlags,
            ImmutableArray <string> tupleElementNames)
        {
            RoslynDebug.Assert(!RoslynString.IsNullOrEmpty(name));
            RoslynDebug.Assert(compileTimeValue != null);

            Name                  = name;
            Location              = location;
            CompileTimeValue      = compileTimeValue;
            DynamicTransformFlags = dynamicTransformFlags.NullToEmpty();
            TupleElementNames     = tupleElementNames.NullToEmpty();
        }
        private static string?NormalizePath(string?path)
        {
            if (RoslynString.IsNullOrEmpty(path))
            {
                return(path);
            }

            var c = path[path.Length - 1];

            if (c == Path.DirectorySeparatorChar || c == Path.AltDirectorySeparatorChar)
            {
                path = path.Substring(0, path.Length - 1);
            }

            return(path);
        }
Exemple #16
0
        public override void LogDiagnostic(Diagnostic diagnostic, SuppressionInfo?suppressionInfo)
        {
            _writer.WriteObjectStart(); // result
            _writer.Write("ruleId", diagnostic.Id);
            int ruleIndex = _descriptors.Add(diagnostic.Descriptor);

            _writer.Write("ruleIndex", ruleIndex);

            _writer.Write("level", GetLevel(diagnostic.Severity));

            string?message = diagnostic.GetMessage(_culture);

            if (!RoslynString.IsNullOrEmpty(message))
            {
                _writer.WriteObjectStart("message");
                _writer.Write("text", message);
                _writer.WriteObjectEnd();
            }

            if (diagnostic.IsSuppressed)
            {
                _writer.WriteArrayStart("suppressions");
                _writer.WriteObjectStart(); // suppression
                _writer.Write("kind", "inSource");
                string?justification = suppressionInfo?.Attribute?.DecodeNamedArgument <string>(
                    "Justification",
                    SpecialType.System_String
                    );
                if (justification != null)
                {
                    _writer.Write("justification", justification);
                }

                _writer.WriteObjectEnd(); // suppression
                _writer.WriteArrayEnd();
            }

            WriteLocations(diagnostic.Location, diagnostic.AdditionalLocations);

            WriteResultProperties(diagnostic);

            _writer.WriteObjectEnd(); // result
        }
Exemple #17
0
        /// <summary>
        /// Gets a value indicating whether the project of the compilation is a Web SDK project based on project properties.
        /// </summary>
        internal static bool IsWebProject(this Compilation compilation, AnalyzerOptions options)
        {
            var propertyValue = options.GetMSBuildPropertyValue(MSBuildPropertyOptionNames.UsingMicrosoftNETSdkWeb, compilation);

            if (string.Equals(propertyValue?.Trim(), "true", StringComparison.OrdinalIgnoreCase))
            {
                return(true);
            }

            propertyValue = options.GetMSBuildPropertyValue(MSBuildPropertyOptionNames.ProjectTypeGuids, compilation);
            if (!RoslynString.IsNullOrEmpty(propertyValue) &&
                (propertyValue.Contains(WebAppProjectGuidString, StringComparison.OrdinalIgnoreCase) ||
                 propertyValue.Contains(WebSiteProjectGuidString, StringComparison.OrdinalIgnoreCase)))
            {
                var guids = propertyValue.Split(';').Select(g => g.Trim()).ToImmutableArray();
                return(guids.Contains(WebAppProjectGuidString, StringComparer.OrdinalIgnoreCase) ||
                       guids.Contains(WebSiteProjectGuidString, StringComparer.OrdinalIgnoreCase));
            }

            return(false);
        }
Exemple #18
0
        protected sealed override async ValueTask <IChecksummedPersistentStorage?> TryOpenDatabaseAsync(
            SolutionKey solutionKey, string workingFolderPath, string databaseFilePath, CancellationToken cancellationToken)
        {
            var solutionFolder = IOUtilities.PerformIO(() => Path.GetDirectoryName(solutionKey.FilePath));

            if (RoslynString.IsNullOrEmpty(solutionFolder))
            {
                return(null);
            }

            var cacheService = await this.CreateCacheServiceAsync(solutionFolder, cancellationToken).ConfigureAwait(false);

            var relativePathBase = await cacheService.GetRelativePathBaseAsync(cancellationToken).ConfigureAwait(false);

            if (string.IsNullOrEmpty(relativePathBase))
            {
                return(null);
            }

            return(new CloudCachePersistentStorage(cacheService, solutionKey, workingFolderPath, relativePathBase, databaseFilePath));
        }
        internal static bool ContainsDroppedIdentifierCharacters(string?name)
        {
            if (RoslynString.IsNullOrEmpty(name))
            {
                return(false);
            }
            if (name[0] == '@')
            {
                return(true);
            }

            int nameLength = name.Length;

            for (int i = 0; i < nameLength; i++)
            {
                if (UnicodeCharacterUtilities.IsFormattingChar(name[i]))
                {
                    return(true);
                }
            }

            return(false);
        }
        internal static async Task <SyntaxNode> GetTransformedSyntaxRootAsync(ISyntaxFacts syntaxFacts, AbstractFileHeaderHelper fileHeaderHelper, SyntaxTrivia newLineTrivia, Document document, string?fileHeaderTemplate, CancellationToken cancellationToken)
        {
            var tree = await document.GetRequiredSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);

            var root = await tree.GetRootAsync(cancellationToken).ConfigureAwait(false);

            // If we weren't given a header lets get the one from editorconfig
            if (fileHeaderTemplate is null &&
                !document.Project.AnalyzerOptions.AnalyzerConfigOptionsProvider.GetOptions(tree).TryGetEditorConfigOption(CodeStyleOptions2.FileHeaderTemplate, out fileHeaderTemplate))
            {
                // No header supplied, no editorconfig setting, nothing to do
                return(root);
            }

            if (RoslynString.IsNullOrEmpty(fileHeaderTemplate))
            {
                // Header template is empty, nothing to do. This shouldn't be possible if this method is called in
                // reaction to a diagnostic, but this method is also used when creating new documents so lets be defensive.
                return(root);
            }

            var expectedFileHeader = fileHeaderTemplate.Replace("{fileName}", Path.GetFileName(document.FilePath));

            var        fileHeader = fileHeaderHelper.ParseFileHeader(root);
            SyntaxNode newSyntaxRoot;

            if (fileHeader.IsMissing)
            {
                newSyntaxRoot = AddHeader(syntaxFacts, fileHeaderHelper, newLineTrivia, root, expectedFileHeader);
            }
            else
            {
                newSyntaxRoot = ReplaceHeader(syntaxFacts, fileHeaderHelper, newLineTrivia, root, expectedFileHeader);
            }

            return(newSyntaxRoot);
        }
Exemple #21
0
        internal ITextBuffer GetOrCreateBufferForPath(string?filePath, IContentType contentType, string languageName, string initialText)
        {
            // If we don't have a file path we'll just make something up for the purpose of this dictionary so all
            // buffers are still held onto. This isn't a file name used in the workspace itself so it's unobservable.
            if (RoslynString.IsNullOrEmpty(filePath))
            {
                filePath = Guid.NewGuid().ToString();
            }

            return(_createdTextBuffers.GetOrAdd(filePath, _ =>
            {
                var textBuffer = EditorFactory.CreateBuffer(ExportProvider, contentType, initialText);

                // Ensure that the editor options on the text buffer matches that of the options that can be directly set in the workspace
                var editorOptions = ExportProvider.GetExportedValue <IEditorOptionsFactoryService>().GetOptions(textBuffer);
                var workspaceOptions = this.Options;

                editorOptions.SetOptionValue(DefaultOptions.ConvertTabsToSpacesOptionId, !workspaceOptions.GetOption(FormattingOptions.UseTabs, languageName));
                editorOptions.SetOptionValue(DefaultOptions.TabSizeOptionId, workspaceOptions.GetOption(FormattingOptions.TabSize, languageName));
                editorOptions.SetOptionValue(DefaultOptions.IndentSizeOptionId, workspaceOptions.GetOption(FormattingOptions.IndentationSize, languageName));

                return textBuffer;
            }));
        }
Exemple #22
0
            public bool Execute(GeneratorExecutionContext context)
            {
                Lang language;

                switch (Language)
                {
                case LanguageNames.CSharp:
                    language = Lang.CSharp;
                    break;

                case LanguageNames.VisualBasic:
                    language = Lang.VisualBasic;
                    break;

                default:
                    LogError(Lang.CSharp, $"GenerateResxSource doesn't support language: '{Language}'");
                    return(false);
                }

                var extension = language switch
                {
                    Lang.CSharp => "cs",
                    Lang.VisualBasic => "vb",
                    _ => "cs",
                };

                OutputTextHintName = ResourceName + $".Designer.{extension}";

                if (string.IsNullOrEmpty(ResourceName))
                {
                    LogError(language, "ResourceName not specified");
                    return(false);
                }

                var resourceAccessName = RoslynString.IsNullOrEmpty(ResourceClassName) ? ResourceName : ResourceClassName;

                SplitName(resourceAccessName, out var namespaceName, out var className);

                var classIndent  = namespaceName == null ? "" : "    ";
                var memberIndent = classIndent + "    ";

                var text = ResourceFile.GetText(context.CancellationToken);

                if (text is null)
                {
                    LogError(language, "ResourceFile was null");
                    return(false);
                }

                var strings = new StringBuilder();

                foreach (var node in XDocument.Parse(text.ToString()).Descendants("data"))
                {
                    var name = node.Attribute("name")?.Value;
                    if (name == null)
                    {
                        LogError(language, "Missing resource name");
                        return(false);
                    }

                    var value = node.Elements("value").FirstOrDefault()?.Value.Trim();
                    if (value == null)
                    {
                        LogError(language, $"Missing resource value: '{name}'");
                        return(false);
                    }

                    if (name.Length == 0)
                    {
                        LogError(language, $"Empty resource name");
                        return(false);
                    }

                    var docCommentString = value.Length > maxDocCommentLength?value.Substring(0, maxDocCommentLength) + " ..." : value;

                    RenderDocComment(language, memberIndent, strings, docCommentString);

                    var identifier = GetIdentifierFromResourceName(name);

                    var defaultValue = IncludeDefaultValues ? ", " + CreateStringLiteral(value, language) : string.Empty;

                    switch (language)
                    {
                    case Lang.CSharp:
                        if (AsConstants)
                        {
                            strings.AppendLine($"{memberIndent}internal const string @{identifier} = \"{name}\";");
                        }
                        else
                        {
                            strings.AppendLine($"{memberIndent}internal static {(IncludeDefaultValues || !Generator.SupportsNullable(context) ? "string" : "string?")} @{identifier} => GetResourceString(\"{name}\"{defaultValue});");
                        }

                        if (EmitFormatMethods)
                        {
                            var resourceString = new ResourceString(name, value);

                            if (resourceString.HasArguments)
                            {
                                RenderDocComment(language, memberIndent, strings, docCommentString);
                                RenderFormatMethod(memberIndent, language, strings, resourceString);
                            }
                        }
                        break;

                    case Lang.VisualBasic:
                        if (AsConstants)
                        {
                            strings.AppendLine($"{memberIndent}Friend Const [{identifier}] As String = \"{name}\"");
                        }
                        else
                        {
                            strings.AppendLine($"{memberIndent}Friend Shared ReadOnly Property [{identifier}] As String");
                            strings.AppendLine($"{memberIndent}  Get");
                            strings.AppendLine($"{memberIndent}    Return GetResourceString(\"{name}\"{defaultValue})");
                            strings.AppendLine($"{memberIndent}  End Get");
                            strings.AppendLine($"{memberIndent}End Property");
                        }

                        if (EmitFormatMethods)
                        {
                            throw new NotImplementedException();
                        }
                        break;

                    default:
                        throw new InvalidOperationException();
                    }
                }

                INamedTypeSymbol?methodImplOptions = context.Compilation.GetOrCreateTypeByMetadataName(typeof(MethodImplOptions).FullName);
                var hasAggressiveInlining          = methodImplOptions?.MemberNames.Contains(nameof(MethodImplOptions.AggressiveInlining)) ?? false;

                var hasNotNullIfNotNull = context.Compilation.GetOrCreateTypeByMetadataName("System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute") is object;

                string?getStringMethod;

                if (OmitGetResourceString)
                {
                    getStringMethod = null;
                }
                else
                {
                    switch (language)
                    {
                    case Lang.CSharp:
                        var getResourceStringAttributes = new List <string>();
                        if (hasAggressiveInlining)
                        {
                            getResourceStringAttributes.Add("[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]");
                        }

                        if (hasNotNullIfNotNull)
                        {
                            getResourceStringAttributes.Add("[return: global::System.Diagnostics.CodeAnalysis.NotNullIfNotNull(\"defaultValue\")]");
                        }

                        getStringMethod = $@"{memberIndent}internal static global::System.Globalization.CultureInfo{(Generator.SupportsNullable(context) ? "?" : "")} Culture {{ get; set; }}
{string.Join(Environment.NewLine, getResourceStringAttributes.Select(attr => memberIndent + attr))}
{memberIndent}internal static {(Generator.SupportsNullable(context) ? "string?" : "string")} GetResourceString(string resourceKey, {(Generator.SupportsNullable(context) ? "string?" : "string")} defaultValue = null) =>  ResourceManager.GetString(resourceKey, Culture) ?? defaultValue;";
                        if (EmitFormatMethods)
                        {
                            getStringMethod += $@"

{memberIndent}private static string GetResourceString(string resourceKey, string[]? formatterNames)
{memberIndent}{{
{memberIndent}   var value = GetResourceString(resourceKey) ?? """";
{memberIndent}   if (formatterNames != null)
{memberIndent}   {{
{memberIndent}       for (var i = 0; i < formatterNames.Length; i++)
{memberIndent}       {{
{memberIndent}           value = value.Replace(""{{"" + formatterNames[i] + ""}}"", ""{{"" + i + ""}}"");
{memberIndent}       }}
{memberIndent}   }}
{memberIndent}   return value;
{memberIndent}}}
";
                        }
                        break;

                    case Lang.VisualBasic:
                        getStringMethod = $@"{memberIndent}Friend Shared Property Culture As Global.System.Globalization.CultureInfo
{memberIndent}<Global.System.Runtime.CompilerServices.MethodImpl(Global.System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)>
{memberIndent}Friend Shared Function GetResourceString(ByVal resourceKey As String, Optional ByVal defaultValue As String = Nothing) As String
{memberIndent}    Return ResourceManager.GetString(resourceKey, Culture)
{memberIndent}End Function";
                        if (EmitFormatMethods)
                        {
                            throw new NotImplementedException();
                        }
                        break;

                    default:
                        throw new InvalidOperationException();
                    }
                }

                string?namespaceStart, namespaceEnd;

                if (namespaceName == null)
                {
                    namespaceStart = namespaceEnd = null;
                }
                else
                {
                    switch (language)
                    {
                    case Lang.CSharp:
                        namespaceStart = $@"namespace {namespaceName}{Environment.NewLine}{{";
                        namespaceEnd   = "}";
                        break;

                    case Lang.VisualBasic:
                        namespaceStart = $"Namespace Global.{namespaceName}";
                        namespaceEnd   = "End Namespace";
                        break;

                    default:
                        throw new InvalidOperationException();
                    }
                }

                string resourceTypeName;
                string?resourceTypeDefinition;

                if (string.IsNullOrEmpty(ResourceClassName) || ResourceName == ResourceClassName)
                {
                    // resource name is same as accessor, no need for a second type.
                    resourceTypeName       = className;
                    resourceTypeDefinition = null;
                }
                else
                {
                    // resource name differs from the access class, need a type for specifying the resources
                    // this empty type must remain as it is required by the .NETNative toolchain for locating resources
                    // once assemblies have been merged into the application
                    resourceTypeName = ResourceName;

                    SplitName(resourceTypeName, out var resourceNamespaceName, out var resourceClassName);
                    var resourceClassIndent = resourceNamespaceName == null ? "" : "    ";

                    switch (language)
                    {
                    case Lang.CSharp:
                        resourceTypeDefinition = $"{resourceClassIndent}internal static class {resourceClassName} {{ }}";
                        if (resourceNamespaceName != null)
                        {
                            resourceTypeDefinition = $@"namespace {resourceNamespaceName}
{{
{resourceTypeDefinition}
}}";
                        }
                        break;

                    case Lang.VisualBasic:
                        resourceTypeDefinition = $@"{resourceClassIndent}Friend Class {resourceClassName}
{resourceClassIndent}End Class";
                        if (resourceNamespaceName != null)
                        {
                            resourceTypeDefinition = $@"Namespace {resourceNamespaceName}
{resourceTypeDefinition}
End Namespace";
                        }
                        break;

                    default:
                        throw new InvalidOperationException();
                    }
                }

                // The ResourceManager property being initialized lazily is an important optimization that lets .NETNative
                // completely remove the ResourceManager class if the disk space saving optimization to strip resources
                // (/DisableExceptionMessages) is turned on in the compiler.
                string result;

                switch (language)
                {
                case Lang.CSharp:
                    result = $@"// <auto-generated/>

{(Generator.SupportsNullable(context) ? "#nullable enable" : "")}
using System.Reflection;

{resourceTypeDefinition}
{namespaceStart}
{classIndent}internal static partial class {className}
{classIndent}{{
{memberIndent}private static global::System.Resources.ResourceManager{(Generator.SupportsNullable(context) ? "?" : "")} s_resourceManager;
{memberIndent}internal static global::System.Resources.ResourceManager ResourceManager => s_resourceManager ?? (s_resourceManager = new global::System.Resources.ResourceManager(typeof({resourceTypeName})));
{getStringMethod}
{strings}
{classIndent}}}
{namespaceEnd}
";
                    break;

                case Lang.VisualBasic:
                    result = $@"' <auto-generated/>

Imports System.Reflection

{resourceTypeDefinition}
{namespaceStart}
{classIndent}Friend Partial Class {className}
{memberIndent}Private Sub New
{memberIndent}End Sub
{memberIndent}
{memberIndent}Private Shared s_resourceManager As Global.System.Resources.ResourceManager
{memberIndent}Friend Shared ReadOnly Property ResourceManager As Global.System.Resources.ResourceManager
{memberIndent}    Get
{memberIndent}        If s_resourceManager Is Nothing Then
{memberIndent}            s_resourceManager = New Global.System.Resources.ResourceManager(GetType({resourceTypeName}))
{memberIndent}        End If
{memberIndent}        Return s_resourceManager
{memberIndent}    End Get
{memberIndent}End Property
{getStringMethod}
{strings}
{classIndent}End Class
{namespaceEnd}
";
                    break;

                default:
                    throw new InvalidOperationException();
                }

                OutputText = SourceText.From(result, Encoding.UTF8, SourceHashAlgorithm.Sha256);
                return(true);
            }
Exemple #23
0
 private static bool IsDocumentLinked(MSB.Framework.ITaskItem documentItem) =>
 !RoslynString.IsNullOrEmpty(documentItem.GetMetadata(MetadataNames.Link));
Exemple #24
0
        protected override int ExecuteTool(string pathToTool, string responseFileCommands, string commandLineCommands)
        {
            if (ProvideCommandLineArgs)
            {
                CommandLineArgs = GetArguments(commandLineCommands, responseFileCommands)
                                  .Select(arg => new TaskItem(arg)).ToArray();
            }

            if (SkipCompilerExecution)
            {
                return(0);
            }

            try
            {
                using var logger = new CompilerServerLogger();
                string workingDir = CurrentDirectoryToUse();
                string?tempDir    = BuildServerConnection.GetTempPath(workingDir);

                if (!UseSharedCompilation ||
                    HasToolBeenOverridden ||
                    !BuildServerConnection.IsCompilerServerSupported)
                {
                    LogCompilationMessage(logger, CompilationKind.Tool, $"using command line tool by design '{pathToTool}'");
                    return(base.ExecuteTool(pathToTool, responseFileCommands, commandLineCommands));
                }

                _sharedCompileCts = new CancellationTokenSource();
                logger.Log($"CommandLine = '{commandLineCommands}'");
                logger.Log($"BuildResponseFile = '{responseFileCommands}'");

                var clientDir = Path.GetDirectoryName(PathToManagedTool);
                if (clientDir is null || tempDir is null)
                {
                    LogCompilationMessage(logger, CompilationKind.Tool, $"using command line tool because we could not find client directory '{PathToManagedTool}'");
                    return(base.ExecuteTool(pathToTool, responseFileCommands, commandLineCommands));
                }

                var buildPaths = new BuildPathsAlt(
                    clientDir: clientDir,
                    workingDir: workingDir,
                    // MSBuild doesn't need the .NET SDK directory
                    sdkDir: null,
                    tempDir: tempDir);

                // Note: using ToolArguments here (the property) since
                // commandLineCommands (the parameter) may have been mucked with
                // (to support using the dotnet cli)
                var responseTask = BuildServerConnection.RunServerCompilationAsync(
                    Language,
                    RoslynString.IsNullOrEmpty(SharedCompilationId) ? null : SharedCompilationId,
                    GetArguments(ToolArguments, responseFileCommands).ToList(),
                    buildPaths,
                    keepAlive: null,
                    libEnvVariable: LibDirectoryToUse(),
                    logger: logger,
                    cancellationToken: _sharedCompileCts.Token);

                responseTask.Wait(_sharedCompileCts.Token);

                ExitCode = HandleResponse(responseTask.Result, pathToTool, responseFileCommands, commandLineCommands, logger);
            }
            catch (OperationCanceledException)
            {
                ExitCode = 0;
            }
            catch (Exception e)
            {
                var util = new TaskLoggingHelper(this);
                util.LogErrorWithCodeFromResources("Compiler_UnexpectedException");
                util.LogErrorFromException(e, showStackTrace: true, showDetail: true, file: null);
                ExitCode = -1;
            }
            finally
            {
                _sharedCompileCts?.Dispose();
                _sharedCompileCts = null;
            }

            return(ExitCode);
        }
        protected override int ExecuteTool(string pathToTool, string responseFileCommands, string commandLineCommands)
        {
            if (ProvideCommandLineArgs)
            {
                CommandLineArgs = GetArguments(commandLineCommands, responseFileCommands)
                                  .Select(arg => new TaskItem(arg)).ToArray();
            }

            if (SkipCompilerExecution)
            {
                return(0);
            }

            try
            {
                string workingDir = CurrentDirectoryToUse();
                string?tempDir    = BuildServerConnection.GetTempPath(workingDir);

                if (!UseSharedCompilation ||
                    HasToolBeenOverridden ||
                    !BuildServerConnection.IsCompilerServerSupported)
                {
                    return(base.ExecuteTool(pathToTool, responseFileCommands, commandLineCommands));
                }

                using var logger = new CompilerServerLogger();
                using (_sharedCompileCts = new CancellationTokenSource())
                {
                    logger.Log($"CommandLine = '{commandLineCommands}'");
                    logger.Log($"BuildResponseFile = '{responseFileCommands}'");

                    var clientDir = Path.GetDirectoryName(PathToManagedTool);
                    if (clientDir is null || tempDir is null)
                    {
                        return(base.ExecuteTool(pathToTool, responseFileCommands, commandLineCommands));
                    }

                    // Note: we can't change the "tool path" printed to the console when we run
                    // the Csc/Vbc task since MSBuild logs it for us before we get here. Instead,
                    // we'll just print our own message that contains the real client location
                    Log.LogMessage(ErrorString.UsingSharedCompilation, clientDir);

                    var buildPaths = new BuildPathsAlt(
                        clientDir: clientDir,
                        workingDir: workingDir,
                        // MSBuild doesn't need the .NET SDK directory
                        sdkDir: null,
                        tempDir: tempDir);

                    // Note: using ToolArguments here (the property) since
                    // commandLineCommands (the parameter) may have been mucked with
                    // (to support using the dotnet cli)
                    var responseTask = BuildServerConnection.RunServerCompilationAsync(
                        Language,
                        RoslynString.IsNullOrEmpty(SharedCompilationId) ? null : SharedCompilationId,
                        GetArguments(ToolArguments, responseFileCommands).ToList(),
                        buildPaths,
                        keepAlive: null,
                        libEnvVariable: LibDirectoryToUse(),
                        logger: logger,
                        cancellationToken: _sharedCompileCts.Token);

                    responseTask.Wait(_sharedCompileCts.Token);

                    var response = responseTask.Result;
                    if (response != null)
                    {
                        ExitCode = HandleResponse(response, pathToTool, responseFileCommands, commandLineCommands, logger);
                    }
                    else
                    {
                        logger.LogError($"Server compilation failed, falling back to {pathToTool}");
                        Log.LogMessage(ErrorString.SharedCompilationFallback, pathToTool);

                        ExitCode = base.ExecuteTool(pathToTool, responseFileCommands, commandLineCommands);
                    }
                }
            }
            catch (OperationCanceledException)
            {
                ExitCode = 0;
            }
            catch (Exception e)
            {
                var util = new TaskLoggingHelper(this);
                util.LogErrorWithCodeFromResources("Compiler_UnexpectedException");
                util.LogErrorFromException(e, showStackTrace: true, showDetail: true, file: null);
                ExitCode = -1;
            }

            return(ExitCode);
        }