// Expects correct arguments.
 internal CompilationOptions(
     OutputKind outputKind,
     string moduleName,
     string mainTypeName,
     string scriptClassName,
     string cryptoKeyContainer,
     string cryptoKeyFile,
     bool?delaySign,
     bool optimize,
     bool checkOverflow,
     int fileAlignment,
     ulong baseAddress,
     Platform platform,
     ReportDiagnostic generalDiagnosticOption,
     int warningLevel,
     IEnumerable <KeyValuePair <string, ReportDiagnostic> > specificDiagnosticOptions,
     bool highEntropyVirtualAddressSpace,
     DebugInformationKind debugInformationKind,
     SubsystemVersion subsystemVersion,
     bool concurrentBuild,
     FileResolver fileResolver,
     MetadataReferenceProvider metadataReferenceProvider,
     AssemblyIdentityComparer assemblyIdentityComparer,
     StrongNameProvider strongNameProvider,
     MetadataImportOptions metadataImportOptions)
 {
     Initialize(
         outputKind, moduleName, mainTypeName, scriptClassName, cryptoKeyContainer, cryptoKeyFile, delaySign, optimize, checkOverflow, fileAlignment,
         baseAddress, platform, generalDiagnosticOption, warningLevel, specificDiagnosticOptions, highEntropyVirtualAddressSpace, debugInformationKind,
         subsystemVersion, concurrentBuild, fileResolver, metadataReferenceProvider, assemblyIdentityComparer, strongNameProvider,
         metadataImportOptions);
 }
Example #2
0
 public DocumentationCommentIncludeCache(FileResolver resolver)
     : base(Size,
            key => MakeValue(resolver, key),
            KeyHashCode,
            KeyValueEquality)
 {
     CacheMissCount = 0;
 }
        internal void Initialize(
            OutputKind outputKind,
            string moduleName,
            string mainTypeName,
            string scriptClassName,
            string cryptoKeyContainer,
            string cryptoKeyFile,
            bool?delaySign,
            bool optimize,
            bool checkOverflow,
            int fileAlignment,
            ulong baseAddress,
            Platform platform,
            ReportDiagnostic generalDiagnosticOption,
            int warningLevel,
            IEnumerable <KeyValuePair <string, ReportDiagnostic> > specificDiagnosticOptions,
            bool highEntropyVirtualAddressSpace,
            DebugInformationKind debugInformationKind,
            SubsystemVersion subsystemVersion,
            bool concurrentBuild,
            FileResolver fileResolver,
            MetadataReferenceProvider metadataReferenceProvider,
            AssemblyIdentityComparer assemblyIdentityComparer,
            StrongNameProvider strongNameProvider,
            MetadataImportOptions metadataImportOptions)
        {
            this.OutputKind                     = outputKind;
            this.ModuleName                     = moduleName;
            this.MainTypeName                   = mainTypeName;
            this.ScriptClassName                = scriptClassName;
            this.CryptoKeyContainer             = cryptoKeyContainer;
            this.CryptoKeyFile                  = cryptoKeyFile;
            this.DelaySign                      = delaySign;
            this.CheckOverflow                  = checkOverflow;
            this.FileAlignment                  = fileAlignment;
            this.BaseAddress                    = baseAddress;
            this.Platform                       = platform;
            this.GeneralDiagnosticOption        = generalDiagnosticOption;
            this.WarningLevel                   = warningLevel;
            this.SpecificDiagnosticOptions      = specificDiagnosticOptions.ToImmutableDictionaryOrEmpty();
            this.HighEntropyVirtualAddressSpace = highEntropyVirtualAddressSpace;
            this.DebugInformationKind           = debugInformationKind;
            this.Optimize                       = optimize;
            this.ConcurrentBuild                = concurrentBuild;
            this.SubsystemVersion               = subsystemVersion;
            this.FileResolver                   = fileResolver ?? FileResolver.Default;
            this.MetadataReferenceProvider      = metadataReferenceProvider ?? MetadataReferenceProvider.Default;
            this.StrongNameProvider             = strongNameProvider;
            this.AssemblyIdentityComparer       = assemblyIdentityComparer ?? AssemblyIdentityComparer.Default;
            this.MetadataImportOptions          = metadataImportOptions;

            this.lazyErrors = new Lazy <ImmutableArray <Diagnostic> >(() =>
            {
                var builder = ArrayBuilder <Diagnostic> .GetInstance();
                ValidateOptions(builder);
                return(builder.ToImmutableAndFree());
            });
        }
Example #4
0
        /// <exception cref="IOException"></exception>
        /// <exception cref="XmlException"></exception>
        /// <exception cref="InvalidOperationException"></exception>
        private static KeyValuePair <string, XDocument> MakeValue(FileResolver resolver, string resolvedPath)
        {
            CacheMissCount++;

            using (Stream stream = resolver.OpenReadChecked(resolvedPath))
            {
                using (XmlReader reader = XmlReader.Create(stream, XmlSettings))
                {
                    var document = XDocument.Load(reader, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo);
                    return(KeyValuePair.Create(resolvedPath, document));
                }
            }
        }
        /// <summary>
        /// Resolves metadata references stored in <see cref="P:MetadataReferences"/> using given file resolver and metadata provider.
        /// If a non-null diagnostic bag <paramref name="diagnosticsOpt"/> is provided, it catches exceptions that may be generated while reading the metadata file and
        /// reports appropriate diagnostics.
        /// Otherwise, if <paramref name="diagnosticsOpt"/> is null, the exceptions are unhandled.
        /// </summary>
        internal IEnumerable <MetadataReference> ResolveMetadataReferences(FileResolver fileResolver, MetadataReferenceProvider metadataProvider, List <DiagnosticInfo> diagnosticsOpt, CommonMessageProvider messageProviderOpt)
        {
            if (fileResolver == null)
            {
                fileResolver = new FileResolver(ReferencePaths, BaseDirectory);
            }

            if (metadataProvider == null)
            {
                metadataProvider = MetadataReferenceProvider.Default;
            }

            foreach (CommandLineReference cmdLineReference in MetadataReferences)
            {
                yield return(cmdLineReference.Resolve(fileResolver, metadataProvider, diagnosticsOpt, messageProviderOpt));
            }
        }
        /// <summary>
        /// Resolves this command line metadata reference to a <see cref="MetadataReference"/> using given file resolver and metadata provider.
        /// </summary>
        /// <exception cref="BadImageFormatException">If the PE image format is invalid and <paramref name="diagnosticsOpt"/> is null.</exception>
        /// <exception cref="FileNotFoundException">If the Metadata file could not be found and <paramref name="diagnosticsOpt"/> is null.</exception>
        /// <exception cref="IOException">If error reading the file from disk and <paramref name="diagnosticsOpt"/> is null.</exception>
        /// <remarks>
        /// NOTE: Other exceptions, apart from those mentioned above, may be generated by the fileResolver or the metadata provider. These are not handled by this method.
        /// </remarks>
        /// <param name="fileResolver">The file resolver to use for assembly name and relative path resolution.</param>
        /// <param name="metadataProvider">Uses to create metadata references from resolved full paths.</param>
        /// <param name="diagnosticsOpt">Optional diagnostics list for storing diagnostics.</param>
        /// <param name="messageProviderOpt">Optional <see cref="CommonMessageProvider"/> for generating diagnostics.</param>
        /// <returns>Returns resolved metadata reference or <see cref="UnresolvedMetadataReference"/>.</returns>
        internal MetadataReference Resolve(FileResolver fileResolver, MetadataReferenceProvider metadataProvider, List <DiagnosticInfo> diagnosticsOpt, CommonMessageProvider messageProviderOpt)
        {
            Debug.Assert(fileResolver != null);
            Debug.Assert(metadataProvider != null);

            string path;

            if (this.IsAssemblyName)
            {
                path = fileResolver.ResolveAssemblyName(this.reference);
                if (path == null)
                {
                    if (diagnosticsOpt != null)
                    {
                        diagnosticsOpt.Add(new DiagnosticInfo(messageProviderOpt, messageProviderOpt.ERR_MetadataFileNotFound, this.reference));
                    }

                    return(new UnresolvedMetadataReference(this.reference, this.properties));
                }
            }
            else
            {
                path = this.reference;
            }

            // use search paths and base path of the resolver - usually these are the same as the paths stored on the arguments:
            string fullPath = fileResolver.ResolveMetadataFileChecked(path, baseFilePath: null);

            if (fullPath == null)
            {
                if (diagnosticsOpt != null)
                {
                    diagnosticsOpt.Add(new DiagnosticInfo(messageProviderOpt, messageProviderOpt.ERR_MetadataFileNotFound, this.reference));
                }

                return(new UnresolvedMetadataReference(this.reference, this.properties));
            }
            else
            {
                return(ResolveMetadataFile(fullPath, this.properties, metadataProvider, this.reference, diagnosticsOpt, messageProviderOpt));
            }
        }
        /// <summary>
        /// Resolves this command line analyzer path to a <see cref="IEnumerable{IDiagnosticAnalyzer}"/> using given file resolver.
        /// </summary>
        /// <param name="fileResolver">The file resolver to use for assembly name and relative path resolution.</param>
        /// <param name="diagnosticsOpt">Optional diagnostics list for storing diagnostics.</param>
        /// <param name="messageProviderOpt">Optional <see cref="CommonMessageProvider"/> for generating diagnostics.</param>
        /// <returns>Returns null if the path is invalid. Otherwise returns the list of analyzer factories from the dll.</returns>
        internal IEnumerable <IDiagnosticAnalyzer> Resolve(FileResolver fileResolver, List <DiagnosticInfo> diagnosticsOpt, CommonMessageProvider messageProviderOpt)
        {
            Debug.Assert(fileResolver != null);

            string fullPath = fileResolver.ResolveMetadataFileChecked(this.analyzer, baseFilePath: null);

            if (fullPath == null)
            {
                if (diagnosticsOpt != null)
                {
                    diagnosticsOpt.Add(new DiagnosticInfo(messageProviderOpt, messageProviderOpt.ERR_MetadataFileNotFound, this.analyzer));
                }

                return(null);
            }
            else
            {
                return(ResolveAnalyzers(fullPath, this.analyzer, diagnosticsOpt, messageProviderOpt));
            }
        }
        /// <summary>
        /// Resolves metadata references stored in command line arguments and reports errors for those that can't be resolved.
        /// </summary>
        internal List <MetadataReference> ResolveMetadataReferences(
            MetadataReferenceProvider metadataProvider,
            List <DiagnosticInfo> diagnostics,
            AssemblyIdentityComparer assemblyIdentityComparer,
            TouchedFileLogger touchedFiles,
            out FileResolver referenceDirectiveResolver)
        {
            using (Logger.LogBlock(FunctionId.Common_CommandLineCompiler_ResolveMetadataReferences))
            {
                string baseDirectory = Arguments.BaseDirectory;
                ImmutableArray <string> absoluteReferencePaths = MakeAbsolute(Arguments.ReferencePaths, baseDirectory);

                FileResolver externalReferenceResolver = new FileResolver(
                    absoluteReferencePaths,
                    baseDirectory,
                    touchedFiles);

                List <MetadataReference> resolved = new List <MetadataReference>();
                ResolveMetadataReferencesFromArguments(metadataProvider, diagnostics, externalReferenceResolver, resolved);

                if (Arguments.IsInteractive)
                {
                    referenceDirectiveResolver = externalReferenceResolver;
                }
                else
                {
                    // when compiling into an assembly (csc/vbc) we only allow #r that match references given on command line:
                    referenceDirectiveResolver = new ExistingReferencesResolver(
                        resolved.Where(r => r.Properties.Kind == MetadataImageKind.Assembly).OfType <MetadataFileReference>().AsImmutable(),
                        absoluteReferencePaths,
                        baseDirectory,
                        assemblyIdentityComparer,
                        touchedFiles);
                }

                return(resolved);
            }
        }
        /// <summary>
        /// Resolves analyzers stored in command line arguments and reports errors for those that can't be resolved.
        /// </summary>
        protected List <IDiagnosticAnalyzer> ResolveAnalyzersFromArguments(List <DiagnosticInfo> diagnostics, TouchedFileLogger touchedFiles)
        {
            List <IDiagnosticAnalyzer> analyzers = new List <IDiagnosticAnalyzer>();

            string baseDirectory = Arguments.BaseDirectory;
            ImmutableArray <string> absoluteReferencePaths = MakeAbsolute(Arguments.ReferencePaths, baseDirectory);

            var fileResolver = new FileResolver(
                absoluteReferencePaths,
                baseDirectory,
                touchedFiles);

            foreach (CommandLineAnalyzer cmdLineAnalyzer in Arguments.Analyzers)
            {
                var analyzersFromAssembly = cmdLineAnalyzer.Resolve(fileResolver, diagnostics, MessageProvider);
                if (analyzersFromAssembly != null)
                {
                    // If there are no analyzers in this assembly, let the user know.
                    if (analyzersFromAssembly.IsEmpty())
                    {
                        diagnostics.Add(new DiagnosticInfo(MessageProvider, MessageProvider.WRN_NoAnalyzerInAssembly, cmdLineAnalyzer.Analyzer));
                    }
                    else
                    {
                        foreach (var analyzer in analyzersFromAssembly)
                        {
                            if (!AreAllDiagnosticsSuppressed(analyzer, Arguments.CompilationOptions.SpecificDiagnosticOptions))
                            {
                                analyzers.Add(analyzer);
                            }
                        }
                    }
                }
            }

            return(analyzers);
        }
        /// <summary>
        /// Create a ProjectInfo structure initialized from a compilers command line arguments.
        /// </summary>
        public static ProjectInfo CreateProjectInfo(Workspace workspace, string projectName, string language, IEnumerable <string> commandLineArgs, string projectDirectory)
        {
            // TODO (tomat): the method may throw all sorts of exceptions.

            var languageServices = LanguageService.GetProvider(workspace, language);

            if (languageServices == null)
            {
                throw new ArgumentException(WorkspacesResources.UnrecognizedLanguageName);
            }

            var commandLineArgumentsFactory = languageServices.GetService <ICommandLineArgumentsFactoryService>();
            var commandLineArguments        = commandLineArgumentsFactory.CreateCommandLineArguments(commandLineArgs, projectDirectory, isInteractive: false);

            // TODO (tomat): to match csc.exe/vbc.exe we should use CommonCommandLineCompiler.ExistingReferencesResolver to deal with #r's
            var fileResolver = new FileResolver(commandLineArguments.ReferencePaths, commandLineArguments.BaseDirectory);

            var strongNameProvider = new DesktopStrongNameProvider(commandLineArguments.KeyFileSearchPaths);

            // resolve all references, ignore those that can't be resolved
            var boundReferences = commandLineArguments.ResolveMetadataReferences(fileResolver, workspace.CurrentSolution.MetadataReferenceProvider);
            var unresolved      = boundReferences.FirstOrDefault(r => r is UnresolvedMetadataReference);

            if (unresolved != null)
            {
                throw new ArgumentException(string.Format(WorkspacesResources.CantResolveMetadataReference, ((UnresolvedMetadataReference)unresolved).Reference));
            }

            AssemblyIdentityComparer assemblyIdentityComparer;

            if (commandLineArguments.AppConfigPath != null)
            {
                try
                {
                    using (var appConfigStream = new FileStream(commandLineArguments.AppConfigPath, FileMode.Open, FileAccess.Read))
                    {
                        assemblyIdentityComparer = DesktopAssemblyIdentityComparer.LoadFromXml(appConfigStream);
                    }
                }
                catch (Exception e)
                {
                    throw new ArgumentException(string.Format(WorkspacesResources.ErrorWhileReadingSpecifiedConfigFile, e.Message));
                }
            }
            else
            {
                assemblyIdentityComparer = DesktopAssemblyIdentityComparer.Default;
            }

            var projectId = ProjectId.CreateNewId(debugName: projectName);

            // construct file infos
            var docs = new List <DocumentInfo>();
            var ids  = new HashSet <DocumentId>();

            foreach (var fileArg in commandLineArguments.SourceFiles)
            {
                var absolutePath = Path.IsPathRooted(fileArg.Path) || string.IsNullOrEmpty(projectDirectory)
                    ? Path.GetFullPath(fileArg.Path)
                    : Path.GetFullPath(Path.Combine(projectDirectory, fileArg.Path));

                var relativePath    = FilePathUtilities.GetRelativePath(projectDirectory, absolutePath);
                var isWithinProject = !Path.IsPathRooted(relativePath);

                var folderRoot = isWithinProject ? Path.GetDirectoryName(relativePath) : "";
                var folders    = isWithinProject ? GetFolders(relativePath) : null;
                var name       = Path.GetFileName(relativePath);
                var id         = GetUniqueDocumentId(projectId, name, folderRoot, ids);

                var doc = DocumentInfo.Create(
                    id: id,
                    name: name,
                    folders: folders,
                    sourceCodeKind: fileArg.IsScript ? SourceCodeKind.Script : SourceCodeKind.Regular,
                    loader: new FileTextLoader(absolutePath),
                    filePath: absolutePath);

                docs.Add(doc);
            }

            // If /out is not specified and the project is a console app the csc.exe finds out the Main method
            // and names the compilation after the file that contains it. We don't want to create a compilation,
            // bind Mains etc. here. Besides the msbuild always includes /out in the command line it produces.
            // So if we don't have the /out argument we name the compilation "<anonymous>".
            string assemblyName = (commandLineArguments.OutputFileName != null) ?
                                  Path.GetFileNameWithoutExtension(commandLineArguments.OutputFileName) : "<anonymous>";

            // TODO (tomat): what should be the assemblyName when compiling a netmodule? Should it be /moduleassemblyname

            var projectInfo = ProjectInfo.Create(
                projectId,
                VersionStamp.Create(),
                projectName,
                assemblyName,
                language: language,
                compilationOptions: commandLineArguments.CompilationOptions
                .WithFileResolver(fileResolver)
                .WithAssemblyIdentityComparer(assemblyIdentityComparer)
                .WithStrongNameProvider(strongNameProvider),
                parseOptions: commandLineArguments.ParseOptions,
                documents: docs,
                metadataReferences: boundReferences);

            return(projectInfo);
        }
 protected abstract CompilationOptions CommonWithFileResolver(FileResolver resolver);
 public CompilationOptions WithFileResolver(FileResolver resolver)
 {
     return(CommonWithFileResolver(resolver));
 }
 /// <summary>
 /// Resolves metadata references stored in <see cref="P:MetadataReferences"/> using given file resolver and metadata provider.
 /// </summary>
 /// <param name="fileResolver">The file resolver to use for assembly name and relative path resolution, or null to use a default.</param>
 /// <param name="metadataProvider">Uses to create metadata references from resolved full paths, or null to use a default.</param>
 /// <returns>Yields resolved metadata references or <see cref="UnresolvedMetadataReference"/>.</returns>
 public IEnumerable <MetadataReference> ResolveMetadataReferences(FileResolver fileResolver = null, MetadataReferenceProvider metadataProvider = null)
 {
     return(ResolveMetadataReferences(fileResolver, metadataProvider, diagnosticsOpt: null, messageProviderOpt: null));
 }
Example #14
0
        /// <summary>
        /// Returns a path for particular location in source that is presented to the user.
        /// </summary>
        /// <remarks>
        /// Used for implementation of <see cref="System.Runtime.CompilerServices.CallerFilePathAttribute"/>
        /// or for embedding source paths in error messages.
        ///
        /// Unlike Dev12 we do account for #line and #ExternalSource directives when determining value for
        /// <see cref="System.Runtime.CompilerServices.CallerFilePathAttribute"/>.
        /// </remarks>
        internal string GetDisplayPath(TextSpan span, FileResolver resolver)
        {
            var mappedSpan = GetMappedLineSpan(span);

            return(resolver.NormalizePath(mappedSpan.Path, basePath: mappedSpan.HasMappedPath?FilePath: null));
        }
Example #15
0
        /// <summary>
        /// Returns false if there were unresolved references in arguments, true otherwise.
        /// </summary>
        protected virtual bool ResolveMetadataReferencesFromArguments(MetadataReferenceProvider metadataProvider, List <DiagnosticInfo> diagnostics, FileResolver externalReferenceResolver, List <MetadataReference> resolved)
        {
            bool result = true;

            foreach (var reference in Arguments.ResolveMetadataReferences(externalReferenceResolver, metadataProvider, diagnostics, MessageProvider))
            {
                if (!reference.IsUnresolved)
                {
                    resolved.Add(reference);
                }
                else
                {
                    result = false;
                    Debug.Assert(diagnostics.Any());
                }
            }

            return(result);
        }