Skip to content

Commit

Permalink
Actually pass canBeEmbedded: true where appropriate
Browse files Browse the repository at this point in the history
  • Loading branch information
nguerrera committed Jul 28, 2016
1 parent 9b66ea8 commit f0bcb4c
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 12 deletions.
1 change: 1 addition & 0 deletions src/Compilers/Core/Portable/CodeAnalysis.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
<Compile Include="InternalUtilities\BlobBuildingStream.cs" />
<Compile Include="GlobalSuppressions.cs" />
<Compile Include="InternalUtilities\IncrementalHash.cs" />
<Compile Include="InternalUtilities\ReadOnlyHashSet.cs" />
<Compile Include="PEWriter\DebugSourceInfo.cs" />
<Compile Include="PEWriter\ExportedType.cs" />
</ItemGroup>
Expand Down
35 changes: 30 additions & 5 deletions src/Compilers/Core/Portable/CommandLine/CommonCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public CommonCompiler(CommandLineParser parser, string responseFile, string[] ar
this.Arguments = parser.Parse(allArgs, baseDirectory, sdkDirectoryOpt, additionalReferenceDirectories);
this.MessageProvider = parser.MessageProvider;
this.AssemblyLoader = assemblyLoader;
this.EmbeddedSourcePaths = GetEmbedddedSourcePaths();

if (Arguments.ParseOptions.Features.ContainsKey("debug-determinism"))
{
Expand Down Expand Up @@ -185,7 +186,7 @@ internal SourceText ReadFileContent(CommandLineSourceFile file, IList<Diagnostic
using (var data = PortableShim.FileStream.Create(filePath, PortableShim.FileMode.Open, PortableShim.FileAccess.Read, PortableShim.FileShare.ReadWrite, bufferSize: 1, options: PortableShim.FileOptions.None))
{
normalizedFilePath = (string)PortableShim.FileStream.Name.GetValue(data);
return EncodedStringText.Create(data, Arguments.Encoding, Arguments.ChecksumAlgorithm);
return EncodedStringText.Create(data, Arguments.Encoding, Arguments.ChecksumAlgorithm, canBeEmbedded: EmbeddedSourcePaths.Contains(file.Path));
}
}
catch (Exception e)
Expand Down Expand Up @@ -666,14 +667,11 @@ private ImmutableArray<EmbeddedText> AcquireEmbeddedTexts(Compilation compilatio
{
var embeddedFiles = Arguments.EmbeddedFiles;

if (embeddedFiles.IsDefaultOrEmpty) // TODO (WIP): change to IsEmpty once set by VB.
if (embeddedFiles.IsDefaultOrEmpty)
{
return ImmutableArray<EmbeddedText>.Empty;
}

// It is the common case that there to be overlap between the source set and the embedded set
// and we do not want to read the source files again here.

var builder = ImmutableArray.CreateBuilder<EmbeddedText>(embeddedFiles.Length);
var trees = Enumerable.ToDictionary(compilation.SyntaxTrees, tree => tree.FilePath);

Expand Down Expand Up @@ -985,5 +983,32 @@ private static string CreateDeterminismKey(CommandLineArguments args, string[] r

return builder.ToString();
}


/// <summary>
/// The set of source file paths that are in the set of embedded paths.
/// This is used to prevent reading source files that are embedded twice.
///
/// It further prevents a race where the file we embed could have changed
/// since the time it was parsed.
/// </summary>
protected IReadOnlySet<string> EmbeddedSourcePaths { get; }

private ReadOnlyHashSet<string> GetEmbedddedSourcePaths()
{
if (Arguments.EmbeddedFiles.IsEmpty)
{
return ReadOnlyHashSet<string>.Empty;
}

var embedSet = new ReadOnlyHashSet<string>(
from file in Arguments.EmbeddedFiles
select FileUtilities.NormalizeAbsolutePath(file.Path));

return new ReadOnlyHashSet<string>(
from file in Arguments.SourceFiles
where embedSet.Contains(FileUtilities.NormalizeAbsolutePath(file.Path))
select file.Path);
}
}
}
24 changes: 17 additions & 7 deletions src/Compilers/Core/Portable/EncodedStringText.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ private static Encoding GetFallbackEncoding()
/// If not specified auto-detect heuristics are used to determine the encoding. If these heuristics fail the decoding is assumed to be Encoding.Default.
/// Note that if the stream starts with Byte Order Mark the value of <paramref name="defaultEncoding"/> is ignored.
/// </param>
/// <param name="canBeEmbedded">Indicates if the file can be embedded in the PDB.</param>
/// <param name="checksumAlgorithm">Hash algorithm used to calculate document checksum.</param>
/// <exception cref="InvalidDataException">
/// The stream content can't be decoded using the specified <paramref name="defaultEncoding"/>, or
Expand All @@ -69,18 +70,21 @@ private static Encoding GetFallbackEncoding()
/// <exception cref="IOException">An IO error occurred while reading from the stream.</exception>
internal static SourceText Create(Stream stream,
Encoding defaultEncoding = null,
SourceHashAlgorithm checksumAlgorithm = SourceHashAlgorithm.Sha1)
SourceHashAlgorithm checksumAlgorithm = SourceHashAlgorithm.Sha1,
bool canBeEmbedded = false)
{
return Create(stream,
() => s_fallbackEncoding,
defaultEncoding: defaultEncoding,
checksumAlgorithm: checksumAlgorithm);
checksumAlgorithm: checksumAlgorithm,
canBeEmbedded: canBeEmbedded);
}

// internal for testing
internal static SourceText Create(Stream stream, Func<Encoding> getEncoding,
Encoding defaultEncoding = null,
SourceHashAlgorithm checksumAlgorithm = SourceHashAlgorithm.Sha1)
SourceHashAlgorithm checksumAlgorithm = SourceHashAlgorithm.Sha1,
bool canBeEmbedded = false)
{
Debug.Assert(stream != null);
Debug.Assert(stream.CanRead && stream.CanSeek);
Expand All @@ -90,7 +94,7 @@ internal static SourceText Create(Stream stream, Func<Encoding> getEncoding,
{
try
{
return Decode(stream, s_utf8Encoding, checksumAlgorithm, throwIfBinaryDetected: false);
return Decode(stream, s_utf8Encoding, checksumAlgorithm, throwIfBinaryDetected: false, canBeEmbedded: canBeEmbedded);
}
catch (DecoderFallbackException)
{
Expand All @@ -115,12 +119,18 @@ internal static SourceText Create(Stream stream, Func<Encoding> getEncoding,
/// <param name="encoding">The expected encoding of the stream. The actual encoding used may be different if byte order marks are detected.</param>
/// <param name="checksumAlgorithm">The checksum algorithm to use.</param>
/// <param name="throwIfBinaryDetected">Throw <see cref="InvalidDataException"/> if binary (non-text) data is detected.</param>
/// <param name="canBeEmbedded">Indicates if the text can be embedded in the PDB.</param>
/// <returns>The <see cref="SourceText"/> decoded from the stream.</returns>
/// <exception cref="DecoderFallbackException">The decoder was unable to decode the stream with the given encoding.</exception>
/// <remarks>
/// internal for unit testing
/// </remarks>
internal static SourceText Decode(Stream data, Encoding encoding, SourceHashAlgorithm checksumAlgorithm, bool throwIfBinaryDetected = false)
internal static SourceText Decode(
Stream data,
Encoding encoding,
SourceHashAlgorithm checksumAlgorithm,
bool throwIfBinaryDetected = false,
bool canBeEmbedded = false)
{
Debug.Assert(data != null);
Debug.Assert(encoding != null);
Expand All @@ -133,11 +143,11 @@ internal static SourceText Decode(Stream data, Encoding encoding, SourceHashAlgo
byte[] buffer = TryGetByteArrayFromStream(data);
if (buffer != null)
{
return SourceText.From(buffer, (int)data.Length, encoding, checksumAlgorithm, throwIfBinaryDetected);
return SourceText.From(buffer, (int)data.Length, encoding, checksumAlgorithm, throwIfBinaryDetected, canBeEmbedded);
}
}

return SourceText.From(data, encoding, checksumAlgorithm, throwIfBinaryDetected);
return SourceText.From(data, encoding, checksumAlgorithm, throwIfBinaryDetected, canBeEmbedded);
}

/// <summary>
Expand Down
22 changes: 22 additions & 0 deletions src/Compilers/Core/Portable/InternalUtilities/ReadOnlyHashSet.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.Collections.Generic;

namespace Roslyn.Utilities
{
internal struct ReadOnlyHashSet<T> : IReadOnlySet<T>
{
private HashSet<T> _set;

public static readonly ReadOnlyHashSet<T> Empty = new ReadOnlyHashSet<T>(new HashSet<T>());

public ReadOnlyHashSet(IEnumerable<T> collection, IEqualityComparer<T> comparer = null)
{
_set = new HashSet<T>(collection, comparer);
}

public int Count => _set.Count;

public bool Contains(T item) => _set.Contains(item);
}
}

0 comments on commit f0bcb4c

Please sign in to comment.