提交 0faaab43 编写于 作者: M Manish Vasani

Merge to latest.

......@@ -623,7 +623,7 @@ private static ThreeState ReportDiagnosticsIfObsoleteInternal(DiagnosticBag diag
ref HashSet<DiagnosticInfo> useSiteDiagnostics,
TypeSymbol throughTypeOpt = null)
{
return this.Flags.Includes(BinderFlags.SuppressAccessChecks) || AccessCheck.IsSymbolAccessible(symbol, within, ref useSiteDiagnostics, throughTypeOpt);
return this.Flags.Includes(BinderFlags.IgnoreAccessibility) || AccessCheck.IsSymbolAccessible(symbol, within, ref useSiteDiagnostics, throughTypeOpt);
}
internal bool IsSymbolAccessibleConditional(
......@@ -634,7 +634,7 @@ private static ThreeState ReportDiagnosticsIfObsoleteInternal(DiagnosticBag diag
ref HashSet<DiagnosticInfo> useSiteDiagnostics,
ConsList<Symbol> basesBeingResolved = null)
{
if (this.Flags.Includes(BinderFlags.SuppressAccessChecks))
if (this.Flags.Includes(BinderFlags.IgnoreAccessibility))
{
failedThroughTypeCheck = false;
return true;
......
......@@ -68,7 +68,7 @@ internal enum BinderFlags : uint
// InCatchBlock are also set.
InNestedFinallyBlock = 1 << 21,
SuppressAccessChecks = 1 << 22,
IgnoreAccessibility = 1 << 22,
ParameterDefaultValue = 1 << 23,
......
......@@ -1262,7 +1262,7 @@ internal bool IsAccessible(Symbol symbol, ref HashSet<DiagnosticInfo> useSiteDia
/// </summary>
internal virtual bool IsAccessible(Symbol symbol, TypeSymbol accessThroughType, out bool failedThroughTypeCheck, ref HashSet<DiagnosticInfo> useSiteDiagnostics, ConsList<Symbol> basesBeingResolved = null)
{
if (this.Flags.Includes(BinderFlags.SuppressAccessChecks))
if (this.Flags.Includes(BinderFlags.IgnoreAccessibility))
{
failedThroughTypeCheck = false;
return true;
......
......@@ -1628,7 +1628,7 @@ internal PointerTypeSymbol CreatePointerTypeSymbol(TypeSymbol elementType)
/// <summary>
/// Gets a new SyntaxTreeSemanticModel for the specified syntax tree.
/// </summary>
public new SemanticModel GetSemanticModel(SyntaxTree syntaxTree, bool suppressAccessChecks)
public new SemanticModel GetSemanticModel(SyntaxTree syntaxTree, bool ignoreAccessibility)
{
if (syntaxTree == null)
{
......@@ -1640,7 +1640,7 @@ public new SemanticModel GetSemanticModel(SyntaxTree syntaxTree, bool suppressAc
throw new ArgumentException("tree");
}
return new SyntaxTreeSemanticModel(this, (SyntaxTree)syntaxTree, suppressAccessChecks);
return new SyntaxTreeSemanticModel(this, (SyntaxTree)syntaxTree, ignoreAccessibility);
}
// When building symbols from the declaration table (lazily), or inside a type, or when
......@@ -2729,9 +2729,9 @@ protected override Compilation CommonPreviousSubmission
get { return _previousSubmission; }
}
protected override SemanticModel CommonGetSemanticModel(SyntaxTree syntaxTree, bool suppressAccessChecks)
protected override SemanticModel CommonGetSemanticModel(SyntaxTree syntaxTree, bool ignoreAccessibility)
{
return this.GetSemanticModel((SyntaxTree)syntaxTree, suppressAccessChecks);
return this.GetSemanticModel((SyntaxTree)syntaxTree, ignoreAccessibility);
}
protected override IEnumerable<SyntaxTree> CommonSyntaxTrees
......
......@@ -2750,8 +2750,8 @@ internal Conversion ClassifyConversionForCast(int position, ExpressionSyntax exp
internal BinderFlags GetSemanticModelBinderFlags()
{
return this.HasAccessChecksSuppressed
? BinderFlags.SemanticModel | BinderFlags.SuppressAccessChecks
return this.IgnoresAccessibility
? BinderFlags.SemanticModel | BinderFlags.IgnoreAccessibility
: BinderFlags.SemanticModel;
}
......
......@@ -26,15 +26,15 @@ internal partial class SyntaxTreeSemanticModel : CSharpSemanticModel
private readonly BinderFactory _binderFactory;
private Func<CSharpSyntaxNode, MemberSemanticModel> _createMemberModelFunction;
private readonly bool _hasAccessChecksSuppressed;
private readonly bool _ignoresAccessibility;
private static readonly Func<CSharpSyntaxNode, bool> s_isMemberDeclarationFunction = IsMemberDeclaration;
internal SyntaxTreeSemanticModel(CSharpCompilation compilation, SyntaxTree syntaxTree, bool suppressAccessChecks = false)
internal SyntaxTreeSemanticModel(CSharpCompilation compilation, SyntaxTree syntaxTree, bool ignoreAccessibility = false)
{
_compilation = compilation;
_syntaxTree = syntaxTree;
_hasAccessChecksSuppressed = suppressAccessChecks;
_ignoresAccessibility = ignoreAccessibility;
if (!this.Compilation.SyntaxTrees.Contains(syntaxTree))
{
......@@ -87,9 +87,9 @@ public override SyntaxTree SyntaxTree
/// <summary>
/// Returns true if this is a SemanticModel that ignores accessibility rules when answering semantic questions.
/// </summary>
public override bool HasAccessChecksSuppressed
public override bool IgnoresAccessibility
{
get { return _hasAccessChecksSuppressed; }
get { return _ignoresAccessibility; }
}
private void VerifySpanForGetDiagnostics(TextSpan? span)
......@@ -903,9 +903,9 @@ private MemberSemanticModel CreateMemberModel(CSharpSyntaxNode node)
{
var outer = _binderFactory.GetBinder(node);
if (this.HasAccessChecksSuppressed)
if (this.IgnoresAccessibility)
{
outer = outer.WithAdditionalFlags(BinderFlags.SuppressAccessChecks);
outer = outer.WithAdditionalFlags(BinderFlags.IgnoreAccessibility);
}
switch (node.Kind())
......
......@@ -10,7 +10,7 @@ Microsoft.CodeAnalysis.CSharp.CSharpCompilation.Clone()
Microsoft.CodeAnalysis.CSharp.CSharpCompilation.ContainsSyntaxTree(Microsoft.CodeAnalysis.SyntaxTree syntaxTree)
Microsoft.CodeAnalysis.CSharp.CSharpCompilation.GetDirectiveReference(Microsoft.CodeAnalysis.CSharp.Syntax.ReferenceDirectiveTriviaSyntax directive)
Microsoft.CodeAnalysis.CSharp.CSharpCompilation.GetMetadataReference(Microsoft.CodeAnalysis.IAssemblySymbol assemblySymbol)
Microsoft.CodeAnalysis.CSharp.CSharpCompilation.GetSemanticModel(Microsoft.CodeAnalysis.SyntaxTree syntaxTree, bool suppressAccessChecks)
Microsoft.CodeAnalysis.CSharp.CSharpCompilation.GetSemanticModel(Microsoft.CodeAnalysis.SyntaxTree syntaxTree, bool ignoreAccessibility)
Microsoft.CodeAnalysis.CSharp.CSharpCompilation.LanguageVersion.get
Microsoft.CodeAnalysis.CSharp.CSharpCompilation.Options.get
Microsoft.CodeAnalysis.CSharp.CSharpCompilation.RemoveAllReferences()
......@@ -2436,7 +2436,7 @@ override Microsoft.CodeAnalysis.CSharp.CSharpCompilation.CommonGetAssemblyOrModu
override Microsoft.CodeAnalysis.CSharp.CSharpCompilation.CommonGetCompilationNamespace(Microsoft.CodeAnalysis.INamespaceSymbol namespaceSymbol)
override Microsoft.CodeAnalysis.CSharp.CSharpCompilation.CommonGetEntryPoint(System.Threading.CancellationToken cancellationToken)
override Microsoft.CodeAnalysis.CSharp.CSharpCompilation.CommonGetMetadataReference(Microsoft.CodeAnalysis.IAssemblySymbol assemblySymbol)
override Microsoft.CodeAnalysis.CSharp.CSharpCompilation.CommonGetSemanticModel(Microsoft.CodeAnalysis.SyntaxTree syntaxTree, bool suppressAccessChecks)
override Microsoft.CodeAnalysis.CSharp.CSharpCompilation.CommonGetSemanticModel(Microsoft.CodeAnalysis.SyntaxTree syntaxTree, bool ignoreAccessibility)
override Microsoft.CodeAnalysis.CSharp.CSharpCompilation.CommonGetSpecialType(Microsoft.CodeAnalysis.SpecialType specialType)
override Microsoft.CodeAnalysis.CSharp.CSharpCompilation.CommonGetSubmissionResultType(out bool hasValue)
override Microsoft.CodeAnalysis.CSharp.CSharpCompilation.CommonGetTypeByMetadataName(string metadataName)
......
using System.IO;
// 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.IO;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
......@@ -9,7 +11,7 @@ namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics
{
public class SuppressAccessibilityChecksTests : CSharpTestBase
{
private static SemanticModel GetSemanticModelWithSuppressAccessChecks()
private static SemanticModel GetSemanticModelWithIgnoreAccessibility()
{
var compilationA = CreateCompilationWithMscorlib(@"
namespace N
......@@ -38,13 +40,13 @@ void Main()
", new MetadataReference[] {referenceA}, TestOptions.ReleaseDll.WithMetadataImportOptions(MetadataImportOptions.All));
var syntaxTree = compilationB.SyntaxTrees[0];
return compilationB.GetSemanticModel(syntaxTree, suppressAccessChecks: true);
return compilationB.GetSemanticModel(syntaxTree, ignoreAccessibility: true);
}
[Fact]
public void TestAccessPrivateMemberOfInternalType()
{
var semanticModel = GetSemanticModelWithSuppressAccessChecks();
var semanticModel = GetSemanticModelWithIgnoreAccessibility();
var invocation = semanticModel.SyntaxTree.GetRoot().DescendantNodes().OfType<InvocationExpressionSyntax>().Single();
var position = invocation.FullSpan.Start;
......@@ -56,7 +58,7 @@ public void TestAccessPrivateMemberOfInternalType()
[Fact]
public void TestAccessChecksInSpeculativeExpression()
{
var semanticModel = GetSemanticModelWithSuppressAccessChecks();
var semanticModel = GetSemanticModelWithIgnoreAccessibility();
var invocation = semanticModel.SyntaxTree.GetRoot().DescendantNodes().OfType<InvocationExpressionSyntax>().Single();
var position = invocation.FullSpan.Start;
......@@ -71,7 +73,7 @@ public void TestAccessChecksInSpeculativeExpression()
[Fact]
public void TestAccessChecksInSpeculativeSemanticModel()
{
var semanticModel = GetSemanticModelWithSuppressAccessChecks();
var semanticModel = GetSemanticModelWithIgnoreAccessibility();
var invocation = semanticModel.SyntaxTree.GetRoot().DescendantNodes().OfType<InvocationExpressionSyntax>().Single();
var position = invocation.FullSpan.Start;
......@@ -108,7 +110,7 @@ static void M()
var tree = SyntaxFactory.ParseSyntaxTree(source);
var comp = CreateCompilationWithMscorlib(tree);
var model = comp.GetSemanticModel(tree,suppressAccessChecks: true);
var model = comp.GetSemanticModel(tree, ignoreAccessibility: true);
var expr = (ExpressionSyntax)tree.GetCompilationUnitRoot().DescendantNodes().OfType<SimpleLambdaExpressionSyntax>().Single().Body;
......@@ -154,7 +156,7 @@ void Main()
", new MetadataReference[] { referenceA }, TestOptions.ReleaseDll.WithMetadataImportOptions(MetadataImportOptions.All));
var syntaxTree = compilationB.SyntaxTrees[0];
var semanticModel = compilationB.GetSemanticModel(syntaxTree, suppressAccessChecks: true);
var semanticModel = compilationB.GetSemanticModel(syntaxTree, ignoreAccessibility: true);
var invocation = syntaxTree.GetRoot().DescendantNodes().OfType<InvocationExpressionSyntax>().Single();
......@@ -200,7 +202,7 @@ private int M
var tree = compilation.SyntaxTrees[0];
var root = tree.GetCompilationUnitRoot();
var model = compilation.GetSemanticModel(tree, suppressAccessChecks: true);
var model = compilation.GetSemanticModel(tree, ignoreAccessibility: true);
AccessorDeclarationSyntax accesorDecl = root.DescendantNodes().OfType<AccessorDeclarationSyntax>().Single();
......
......@@ -38,7 +38,7 @@
/r:System.Web.Mobile.dll
/r:System.Web.RegularExpressions.dll
/r:System.Web.Services.dll
/r:System.Windows.Forms.Dll
/r:System.Windows.Forms.dll
/r:System.Workflow.Activities.dll
/r:System.Workflow.ComponentModel.dll
/r:System.Workflow.Runtime.dll
......
......@@ -23,6 +23,7 @@
</Compile>
<Compile Include="AnalyzerFileReferenceTests.cs" />
<Compile Include="AsyncQueueTests.cs" />
<Compile Include="Collections\BoxesTest.cs" />
<Compile Include="Diagnostics\DiagnosticLocalizationTests.cs" />
<Compile Include="Emit\EmitOptionsTests.cs" />
<Compile Include="Emit\CustomDebugInfoReaderTests.cs" />
......
using Xunit;
namespace Microsoft.CodeAnalysis.UnitTests.Collections
{
public class BoxesTest
{
[Fact]
public void AllBoxesTest()
{
// Boolean
Assert.Same(Boxes.Box(true), Boxes.Box(true));
Assert.Same(Boxes.Box(false), Boxes.Box(false));
Assert.NotSame(Boxes.Box(true), Boxes.Box(false));
// Byte
Assert.Same(Boxes.Box((byte)0), Boxes.Box((byte)0));
Assert.NotSame(Boxes.Box((byte)3), Boxes.Box((byte)3));
// SByte
Assert.Same(Boxes.Box((sbyte)0), Boxes.Box((sbyte)0));
Assert.NotSame(Boxes.Box((sbyte)3), Boxes.Box((sbyte)3));
// Int16
Assert.Same(Boxes.Box((short)0), Boxes.Box((short)0));
Assert.NotSame(Boxes.Box((short)3), Boxes.Box((short)3));
// UInt16
Assert.Same(Boxes.Box((ushort)0), Boxes.Box((ushort)0));
Assert.NotSame(Boxes.Box((ushort)3), Boxes.Box((ushort)3));
// Int32
Assert.Same(Boxes.Box(0), Boxes.Box(0));
Assert.Same(Boxes.Box(1), Boxes.Box(1));
Assert.Same(Boxes.BoxedInt32Zero, Boxes.Box(0));
Assert.Same(Boxes.BoxedInt32One, Boxes.Box(1));
Assert.NotSame(Boxes.Box(3), Boxes.Box(3));
// UInt32
Assert.Same(Boxes.Box(0u), Boxes.Box(0u));
Assert.NotSame(Boxes.Box(3u), Boxes.Box(3u));
// Int64
Assert.Same(Boxes.Box(0L), Boxes.Box(0L));
Assert.NotSame(Boxes.Box(3L), Boxes.Box(3L));
// UInt64
Assert.Same(Boxes.Box(0UL), Boxes.Box(0UL));
Assert.NotSame(Boxes.Box(3UL), Boxes.Box(3UL));
// Single
Assert.Same(Boxes.Box(0.0f), Boxes.Box(0.0f));
Assert.NotSame(Boxes.Box(0.0f), Boxes.Box(-0.0f));
Assert.NotSame(Boxes.Box(1.0f), Boxes.Box(1.0f));
// Double
Assert.Same(Boxes.Box(0.0), Boxes.Box(0.0));
Assert.NotSame(Boxes.Box(0.0), Boxes.Box(-0.0));
Assert.NotSame(Boxes.Box(1.0), Boxes.Box(1.0));
// Decimal
Assert.Same(Boxes.Box(decimal.Zero), Boxes.Box(0m));
Assert.NotSame(Boxes.Box(0m), Boxes.Box(decimal.Negate(0m)));
decimal strangeDecimalZero = new decimal(0, 0, 0, false, 10);
Assert.Equal(decimal.Zero, strangeDecimalZero);
Assert.NotSame(Boxes.Box(decimal.Zero), Boxes.Box(strangeDecimalZero));
// Char
Assert.Same(Boxes.Box('\0'), Boxes.Box('\0'));
Assert.Same(Boxes.Box('*'), Boxes.Box('*'));
Assert.Same(Boxes.Box('0'), Boxes.Box('0'));
Assert.NotSame(Boxes.Box('\u1234'), Boxes.Box('\u1234')); // non ASCII
}
}
}
......@@ -93,43 +93,6 @@ public void CheckSum_SHA256()
Assert.Equal("f1945cd6 c19e56b3 c1c78943 ef5ec181 16907a4c a1efc40a 57d48ab1 db7adfc5", StringTextTest.ChecksumToHexQuads(checksum));
}
[Fact]
public void TryReadByteOrderMark()
{
Assert.Null(EncodedStringText.TryReadByteOrderMark(new MemoryStream(new byte[0])));
Assert.Null(EncodedStringText.TryReadByteOrderMark(new MemoryStream(new byte[] { 0xef })));
Assert.Null(EncodedStringText.TryReadByteOrderMark(new MemoryStream(new byte[] { 0xef, 0xbb })));
Assert.Equal(Encoding.UTF8, EncodedStringText.TryReadByteOrderMark(new MemoryStream(new byte[] { 0xef, 0xBB, 0xBF })));
Assert.Null(EncodedStringText.TryReadByteOrderMark(new MemoryStream(new byte[] { 0xff })));
Assert.Equal(Encoding.Unicode, EncodedStringText.TryReadByteOrderMark(new MemoryStream(new byte[] { 0xff, 0xfe })));
Assert.Null(EncodedStringText.TryReadByteOrderMark(new MemoryStream(new byte[] { 0xfe })));
Assert.Equal(Encoding.BigEndianUnicode, EncodedStringText.TryReadByteOrderMark(new MemoryStream(new byte[] { 0xfe, 0xff })));
}
[Fact]
public void IsBinary()
{
Assert.False(EncodedStringText.IsBinary(""));
Assert.False(EncodedStringText.IsBinary("\0abc"));
Assert.False(EncodedStringText.IsBinary("a\0bc"));
Assert.False(EncodedStringText.IsBinary("abc\0"));
Assert.False(EncodedStringText.IsBinary("a\0b\0c"));
Assert.True(EncodedStringText.IsBinary("\0\0abc"));
Assert.True(EncodedStringText.IsBinary("a\0\0bc"));
Assert.True(EncodedStringText.IsBinary("abc\0\0"));
var encoding = Encoding.GetEncoding(1252);
Assert.False(EncodedStringText.IsBinary(encoding.GetString(new byte[] { 0x81, 0x8D, 0x8F, 0x90, 0x9D })));
// Unicode string: äëïöüû
Assert.False(EncodedStringText.IsBinary("abc def baz aeiouy \u00E4\u00EB\u00EF\u00F6\u00FC\u00FB"));
Assert.True(EncodedStringText.IsBinary(encoding.GetString(ProprietaryTestResources.NetFX.v4_0_30319.System)));
}
[Fact]
public void Decode_NonUtf8()
{
......
......@@ -109,7 +109,8 @@ public void CopyToLargeTest()
}
}
var text = CreateSourceText(stream);
var text = SourceText.From(stream);
Assert.IsType(typeof(LargeEncodedText), text);
char[] buffer = new char[HelloWorld.Length];
for (int start = 0; start < text.Length; start += HelloWorld.Length)
......@@ -119,5 +120,196 @@ public void CopyToLargeTest()
}
}
}
private static void CheckEqualLine(TextLine first, TextLine second)
{
Assert.Equal(first, second);
#if false
// We do not guarantee either identity or Equals!
Assert.Equal(first.Extent, second.Extent);
Assert.Equal(first.ExtentIncludingLineBreak, second.ExtentIncludingLineBreak);
#endif
}
private static void CheckNotEqualLine(TextLine first, TextLine second)
{
Assert.NotEqual(first, second);
#if false
Assert.NotEqual(first, second);
Assert.NotEqual(first.Extent, second.Extent);
Assert.NotEqual(first.ExtentIncludingLineBreak, second.ExtentIncludingLineBreak);
#endif
}
private static void CheckLine(SourceText text, int lineNumber, int start, int length, int newlineLength, string lineText)
{
var textLine = text.Lines[lineNumber];
Assert.Equal(start, textLine.Start);
Assert.Equal(start + length, textLine.End);
Assert.Equal(start + length + newlineLength, textLine.EndIncludingLineBreak);
Assert.Equal(start, textLine.Span.Start);
Assert.Equal(length, textLine.Span.Length);
Assert.Equal(start, textLine.SpanIncludingLineBreak.Start);
Assert.Equal(length + newlineLength, textLine.SpanIncludingLineBreak.Length);
Assert.Equal(lineNumber, textLine.LineNumber);
Assert.Equal(lineText, textLine.ToString());
Assert.Equal(text.ToString().Substring(start, length), textLine.ToString());
CheckEqualLine(textLine, text.Lines[lineNumber]);
for (int p = textLine.Start; p < textLine.EndIncludingLineBreak; ++p)
{
CheckEqualLine(textLine, text.Lines.GetLineFromPosition(p));
Assert.Equal(lineNumber, text.Lines.IndexOf(p));
Assert.Equal(lineNumber, text.Lines.GetLinePosition(p).Line);
Assert.Equal(p - start, text.Lines.GetLinePosition(p).Character);
}
if (start != 0)
{
CheckNotEqualLine(textLine, text.Lines.GetLineFromPosition(start - 1));
Assert.Equal(lineNumber - 1, text.Lines.IndexOf(start - 1));
Assert.Equal(lineNumber - 1, text.Lines.GetLinePosition(start - 1).Line);
}
int nextPosition = start + length + newlineLength;
if (nextPosition < text.Length)
{
CheckNotEqualLine(textLine, text.Lines.GetLineFromPosition(nextPosition));
Assert.Equal(lineNumber + 1, text.Lines.IndexOf(nextPosition));
Assert.Equal(lineNumber + 1, text.Lines.GetLinePosition(nextPosition).Line);
}
}
[Fact]
public void NewLines1()
{
var data = CreateSourceText("foo" + Environment.NewLine + " bar");
Assert.Equal(2, data.Lines.Count);
CheckLine(data, lineNumber: 0, start: 0, length: 3, newlineLength: 2, lineText: "foo");
CheckLine(data, lineNumber: 1, start: 5, length: 4, newlineLength: 0, lineText: " bar");
}
[Fact]
public void NewLines2()
{
var text =
@"foo
bar
baz";
var data = CreateSourceText(text);
Assert.Equal(3, data.Lines.Count);
CheckLine(data, lineNumber: 0, start: 0, length: 3, newlineLength: 2, lineText: "foo");
CheckLine(data, lineNumber: 1, start: 5, length: 3, newlineLength: 2, lineText: "bar");
CheckLine(data, lineNumber: 2, start: 10, length: 3, newlineLength: 0, lineText: "baz");
}
[Fact]
public void NewLines3()
{
var data = CreateSourceText("foo\r\nbar");
Assert.Equal(2, data.Lines.Count);
CheckLine(data, lineNumber: 0, start: 0, length: 3, newlineLength: 2, lineText: "foo");
CheckLine(data, lineNumber: 1, start: 5, length: 3, newlineLength: 0, lineText: "bar");
}
[Fact]
public void NewLines4()
{
var data = CreateSourceText("foo\n\rbar\u2028");
Assert.Equal(4, data.Lines.Count);
CheckLine(data, lineNumber: 0, start: 0, length: 3, newlineLength: 1, lineText: "foo");
CheckLine(data, lineNumber: 1, start: 4, length: 0, newlineLength: 1, lineText: "");
CheckLine(data, lineNumber: 2, start: 5, length: 3, newlineLength: 1, lineText: "bar");
CheckLine(data, lineNumber: 3, start: 9, length: 0, newlineLength: 0, lineText: "");
}
[Fact]
public void NewLines5()
{
// Trailing CR
var data = CreateSourceText("foo\r");
Assert.Equal(2, data.Lines.Count);
CheckLine(data, lineNumber: 0, start: 0, length: 3, newlineLength: 1, lineText: "foo");
CheckLine(data, lineNumber: 1, start: 4, length: 0, newlineLength: 0, lineText: "");
}
[Fact]
public void NewLines6()
{
// Trailing CR+LF
var data = CreateSourceText("foo\r\n");
Assert.Equal(2, data.Lines.Count);
CheckLine(data, lineNumber: 0, start: 0, length: 3, newlineLength: 2, lineText: "foo");
CheckLine(data, lineNumber: 1, start: 5, length: 0, newlineLength: 0, lineText: "");
}
[Fact]
public void NewLines7()
{
// Consecutive CR
var data = CreateSourceText("foo\r\rbar");
Assert.Equal(3, data.Lines.Count);
CheckLine(data, lineNumber: 0, start: 0, length: 3, newlineLength: 1, lineText: "foo");
CheckLine(data, lineNumber: 1, start: 4, length: 0, newlineLength: 1, lineText: "");
CheckLine(data, lineNumber: 2, start: 5, length: 3, newlineLength: 0, lineText: "bar");
}
[Fact]
public void NewLines8()
{
// Mix CR with CR+LF
const string cr = "\r";
const string crLf = "\r\n";
var data = CreateSourceText("foo" + cr + crLf + cr + "bar");
Assert.Equal(4, data.Lines.Count);
CheckLine(data, lineNumber: 0, start: 0, length: 3, newlineLength: 1, lineText: "foo");
CheckLine(data, lineNumber: 1, start: 4, length: 0, newlineLength: 2, lineText: "");
CheckLine(data, lineNumber: 2, start: 6, length: 0, newlineLength: 1, lineText: "");
CheckLine(data, lineNumber: 3, start: 7, length: 3, newlineLength: 0, lineText: "bar");
}
[Fact]
public void NewLines9()
{
// Mix CR with CR+LF
const string cr = "\r";
const string crLf = "\r\n";
const string lf = "\n";
var data = CreateSourceText("foo" + cr + crLf + lf + "bar");
Assert.Equal(4, data.Lines.Count);
CheckLine(data, lineNumber: 0, start: 0, length: 3, newlineLength: 1, lineText: "foo");
CheckLine(data, lineNumber: 1, start: 4, length: 0, newlineLength: 2, lineText: "");
CheckLine(data, lineNumber: 2, start: 6, length: 0, newlineLength: 1, lineText: "");
CheckLine(data, lineNumber: 3, start: 7, length: 3, newlineLength: 0, lineText: "bar");
}
[Fact]
public void Empty()
{
var data = CreateSourceText("");
Assert.Equal(1, data.Lines.Count);
CheckLine(data, lineNumber: 0, start: 0, length: 0, newlineLength: 0, lineText: "");
}
[Fact]
public void LinesGetText1()
{
var text =
@"foo
bar baz";
var data = CreateSourceText(text);
Assert.Equal(2, data.Lines.Count);
Assert.Equal("foo", data.Lines[0].ToString());
Assert.Equal("bar baz", data.Lines[1].ToString());
}
[Fact]
public void LinesGetText2()
{
var text = "foo";
var data = CreateSourceText(text);
Assert.Equal("foo", data.Lines[0].ToString());
}
}
}
\ No newline at end of file
// 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;
using System.Collections.Immutable;
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.CodeAnalysis.Text;
using Xunit;
using ProprietaryTestResources = Microsoft.CodeAnalysis.Test.Resources.Proprietary;
namespace Microsoft.CodeAnalysis.UnitTests.Text
{
......@@ -15,31 +14,60 @@ public class SourceTextTests
private static readonly Encoding s_utf8 = Encoding.UTF8;
private static readonly Encoding s_utf8Bom = new UTF8Encoding(encoderShouldEmitUTF8Identifier: true);
private static readonly Encoding s_unicode = Encoding.Unicode;
private const string HelloWorld = "Hello, World!";
[Fact]
public void Empty()
{
TestIsEmpty(SourceText.From(string.Empty));
TestIsEmpty(SourceText.From(new byte[0], 0));
TestIsEmpty(SourceText.From(new MemoryStream()));
}
private static void TestIsEmpty(SourceText text)
{
Assert.Equal(0, text.Length);
Assert.Same(string.Empty, text.ToString());
Assert.Equal(1, text.Lines.Count);
Assert.Equal(0, text.Lines[0].Span.Length);
}
[Fact]
public void Encoding1()
{
Assert.Same(s_utf8, SourceText.From("foo", s_utf8).Encoding);
Assert.Same(s_unicode, SourceText.From("foo", s_unicode).Encoding);
Assert.Same(s_unicode, SourceText.From(new MemoryStream(s_unicode.GetBytes("foo")), s_unicode).Encoding);
Assert.Same(s_utf8, SourceText.From(HelloWorld, s_utf8).Encoding);
Assert.Same(s_unicode, SourceText.From(HelloWorld, s_unicode).Encoding);
var bytes = s_unicode.GetBytes(HelloWorld);
Assert.Same(s_unicode, SourceText.From(bytes, bytes.Length, s_unicode).Encoding);
var stream = new MemoryStream(bytes);
Assert.Same(s_unicode, SourceText.From(stream, s_unicode).Encoding);
}
[Fact]
public void EncodingBOM()
{
var stream = new MemoryStream(s_utf8Bom.GetPreamble().Concat(s_utf8Bom.GetBytes("abc")).ToArray());
var bytes = s_utf8Bom.GetPreamble().Concat(s_utf8Bom.GetBytes("abc")).ToArray();
Assert.Equal(s_utf8.EncodingName, SourceText.From(bytes, bytes.Length, s_unicode).Encoding.EncodingName);
var stream = new MemoryStream(bytes);
Assert.Equal(s_utf8.EncodingName, SourceText.From(stream, s_unicode).Encoding.EncodingName);
}
[Fact]
public void ChecksumAlgorithm1()
{
Assert.Equal(SourceHashAlgorithm.Sha1, SourceText.From("foo").ChecksumAlgorithm);
Assert.Equal(SourceHashAlgorithm.Sha1, SourceText.From("foo", checksumAlgorithm: SourceHashAlgorithm.Sha1).ChecksumAlgorithm);
Assert.Equal(SourceHashAlgorithm.Sha256, SourceText.From("foo", checksumAlgorithm: SourceHashAlgorithm.Sha256).ChecksumAlgorithm);
Assert.Equal(SourceHashAlgorithm.Sha1, SourceText.From(HelloWorld).ChecksumAlgorithm);
Assert.Equal(SourceHashAlgorithm.Sha1, SourceText.From(HelloWorld, checksumAlgorithm: SourceHashAlgorithm.Sha1).ChecksumAlgorithm);
Assert.Equal(SourceHashAlgorithm.Sha256, SourceText.From(HelloWorld, checksumAlgorithm: SourceHashAlgorithm.Sha256).ChecksumAlgorithm);
var stream = new MemoryStream(s_unicode.GetBytes("foo"));
var bytes = s_unicode.GetBytes(HelloWorld);
Assert.Equal(SourceHashAlgorithm.Sha1, SourceText.From(bytes, bytes.Length).ChecksumAlgorithm);
Assert.Equal(SourceHashAlgorithm.Sha1, SourceText.From(bytes, bytes.Length, checksumAlgorithm: SourceHashAlgorithm.Sha1).ChecksumAlgorithm);
Assert.Equal(SourceHashAlgorithm.Sha256, SourceText.From(bytes, bytes.Length, checksumAlgorithm: SourceHashAlgorithm.Sha256).ChecksumAlgorithm);
var stream = new MemoryStream(bytes);
Assert.Equal(SourceHashAlgorithm.Sha1, SourceText.From(stream).ChecksumAlgorithm);
Assert.Equal(SourceHashAlgorithm.Sha1, SourceText.From(stream, checksumAlgorithm: SourceHashAlgorithm.Sha1).ChecksumAlgorithm);
Assert.Equal(SourceHashAlgorithm.Sha256, SourceText.From(stream, checksumAlgorithm: SourceHashAlgorithm.Sha256).ChecksumAlgorithm);
......@@ -48,14 +76,14 @@ public void ChecksumAlgorithm1()
[Fact]
public void ContentEquals()
{
var f = SourceText.From("foo", s_utf8);
var f = SourceText.From(HelloWorld, s_utf8);
Assert.True(f.ContentEquals(SourceText.From("foo", s_utf8)));
Assert.False(f.ContentEquals(SourceText.From("fooo", s_utf8)));
Assert.True(SourceText.From("foo", s_utf8).ContentEquals(SourceText.From("foo", s_utf8)));
Assert.True(f.ContentEquals(SourceText.From(HelloWorld, s_utf8)));
Assert.False(f.ContentEquals(SourceText.From(HelloWorld + "o", s_utf8)));
Assert.True(SourceText.From(HelloWorld, s_utf8).ContentEquals(SourceText.From(HelloWorld, s_utf8)));
var e1 = EncodedStringText.Create(new MemoryStream(s_unicode.GetBytes("foo")), s_unicode);
var e2 = EncodedStringText.Create(new MemoryStream(s_utf8.GetBytes("foo")), s_utf8);
var e1 = EncodedStringText.Create(new MemoryStream(s_unicode.GetBytes(HelloWorld)), s_unicode);
var e2 = EncodedStringText.Create(new MemoryStream(s_utf8.GetBytes(HelloWorld)), s_utf8);
Assert.True(e1.ContentEquals(e1));
Assert.True(f.ContentEquals(e1));
......@@ -65,5 +93,73 @@ public void ContentEquals()
Assert.True(e1.ContentEquals(e2));
Assert.True(e2.ContentEquals(e1));
}
[Fact]
public void IsBinary()
{
Assert.False(SourceText.IsBinary(""));
Assert.False(SourceText.IsBinary("\0abc"));
Assert.False(SourceText.IsBinary("a\0bc"));
Assert.False(SourceText.IsBinary("abc\0"));
Assert.False(SourceText.IsBinary("a\0b\0c"));
Assert.True(SourceText.IsBinary("\0\0abc"));
Assert.True(SourceText.IsBinary("a\0\0bc"));
Assert.True(SourceText.IsBinary("abc\0\0"));
var encoding = Encoding.GetEncoding(1252);
Assert.False(SourceText.IsBinary(encoding.GetString(new byte[] { 0x81, 0x8D, 0x8F, 0x90, 0x9D })));
// Unicode string: äëïöüû
Assert.False(SourceText.IsBinary("abc def baz aeiouy \u00E4\u00EB\u00EF\u00F6\u00FC\u00FB"));
Assert.True(SourceText.IsBinary(encoding.GetString(ProprietaryTestResources.NetFX.v4_0_30319.System)));
}
[Fact]
public void FromThrowsIfBinary()
{
var bytes = ProprietaryTestResources.NetFX.v4_0_30319.System;
Assert.Throws<InvalidDataException>(() => SourceText.From(bytes, bytes.Length, throwIfBinaryDetected: true));
var stream = new MemoryStream(bytes);
Assert.Throws<InvalidDataException>(() => SourceText.From(stream, throwIfBinaryDetected: true));
}
private static void TestTryReadByteOrderMark(Encoding expectedEncoding, int expectedPreambleLength, byte[] data)
{
TestTryReadByteOrderMark(expectedEncoding, expectedPreambleLength, data, data == null ? 0 : data.Length);
}
private static void TestTryReadByteOrderMark(Encoding expectedEncoding, int expectedPreambleLength, byte[] data, int validLength)
{
int actualPreambleLength;
Encoding actualEncoding = SourceText.TryReadByteOrderMark(data, validLength, out actualPreambleLength);
if (expectedEncoding == null)
{
Assert.Null(actualEncoding);
}
else
{
Assert.Equal(expectedEncoding, actualEncoding);
}
Assert.Equal(expectedPreambleLength, actualPreambleLength);
}
[Fact]
public void TryReadByteOrderMark()
{
TestTryReadByteOrderMark(expectedEncoding: null, expectedPreambleLength: 0, data: new byte[0]);
TestTryReadByteOrderMark(expectedEncoding: null, expectedPreambleLength: 0, data: new byte[] { 0xef });
TestTryReadByteOrderMark(expectedEncoding: null, expectedPreambleLength: 0, data: new byte[] { 0xef, 0xbb });
TestTryReadByteOrderMark(expectedEncoding: null, expectedPreambleLength: 0, data: new byte[] { 0xef, 0xBB, 0xBF }, validLength: 2);
TestTryReadByteOrderMark(expectedEncoding: Encoding.UTF8, expectedPreambleLength: 3, data: new byte[] { 0xef, 0xBB, 0xBF });
TestTryReadByteOrderMark(expectedEncoding: null, expectedPreambleLength: 0, data: new byte[] { 0xff });
TestTryReadByteOrderMark(expectedEncoding: Encoding.Unicode, expectedPreambleLength: 2, data: new byte[] { 0xff, 0xfe });
TestTryReadByteOrderMark(expectedEncoding: null, expectedPreambleLength: 0, data: new byte[] { 0xfe });
TestTryReadByteOrderMark(expectedEncoding: Encoding.BigEndianUnicode, expectedPreambleLength: 2, data: new byte[] { 0xfe, 0xff });
}
}
}
......@@ -236,6 +236,9 @@ public void FromStream_CheckSum_BOM()
[Fact]
public void FromStream_CheckSum_NoBOM()
{
// Note: The 0x95 is outside the ASCII range, so a question mark will
// be substituted in decoded text. Note, however, that the checksum
// should be derived from the original input.
var bytes = new byte[] { 0x61, 0x62, 0x95 };
var source = SourceText.From(new MemoryStream(bytes), Encoding.ASCII);
......
......@@ -91,7 +91,6 @@
<Compile Include="Interop\IClrStrongName.cs" />
<Compile Include="Interop\SuppressUnmanagedCodeSecurityAttribute.cs" />
<Compile Include="IVsSQM.cs" />
<Compile Include="LargeEncodedText.cs" />
<Compile Include="MetadataCache.cs" />
<Compile Include="AnalyzerFileReference.cs" />
<Compile Include="MetadataFileReference.cs" />
......
// 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;
using System.Collections.Immutable;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Threading;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Text
{
internal sealed class EncodedStringText : SourceText
internal static class EncodedStringText
{
/// <summary>
/// Underlying string on which this SourceText instance is based
/// </summary>
private readonly string _source;
private readonly Encoding _encoding;
private const int LargeObjectHeapLimit = 80 * 1024; // 80KB
private EncodedStringText(string source, Encoding encoding, ImmutableArray<byte> checksum, SourceHashAlgorithm checksumAlgorithm, bool throwIfBinary)
: base(checksum: checksum, checksumAlgorithm: checksumAlgorithm)
{
if (throwIfBinary && IsBinary(source))
{
throw new InvalidDataException();
}
Debug.Assert(source != null);
Debug.Assert(encoding != null);
_source = source;
_encoding = encoding;
}
private const int LargeObjectHeapLimitInChars = 40 * 1024; // 40KB
/// <summary>
/// Encoding to use when there is no byte order mark (BOM) on the stream. This encoder may throw a <see cref="DecoderFallbackException"/>
......@@ -42,9 +19,13 @@ private EncodedStringText(string source, Encoding encoding, ImmutableArray<byte>
private static readonly Encoding FallbackEncoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true);
/// <summary>
/// Initializes an instance of <see cref="EncodedStringText"/> with provided bytes.
/// Initializes an instance of <see cref="SourceText"/> from the provided stream. This version differs
/// from <see cref="SourceText.From(Stream, Encoding, SourceHashAlgorithm, bool)"/> in two ways:
/// 1. It attempts to minimize allocations by trying to read the stream into a byte array.
/// 2. If <paramref name="defaultEncoding"/> is null, it will first try UTF8 and, if that fails, it will
/// try <see cref="Encoding.Default"/>.
/// </summary>
/// <param name="stream"></param>
/// <param name="stream">The stream containing encoded text.</param>
/// <param name="defaultEncoding">
/// Specifies an encoding to be used if the actual encoding can't be determined from the stream content (the stream doesn't start with Byte Order Mark).
/// If not specified auto-detect heuristics are used to determine the encoding. If these heuristics fail the decoding is assumed to be <see cref="Encoding.Default"/>.
......@@ -84,156 +65,36 @@ internal static SourceText Create(Stream stream, Encoding defaultEncoding = null
}
}
public override Encoding Encoding
{
get { return _encoding; }
}
/// <summary>
/// Underlying string which is the source of this SourceText instance
/// </summary>
public string Source
{
get { return _source; }
}
/// <summary>
/// The length of the text represented by <see cref="EncodedStringText"/>.
/// </summary>
public override int Length
{
get { return this.Source.Length; }
}
/// <summary>
/// Returns a character at given position.
/// </summary>
/// <param name="position">The position to get the character from.</param>
/// <returns>The character.</returns>
/// <exception cref="ArgumentOutOfRangeException">When position is negative or
/// greater than <see cref="Length"/>.</exception>
public override char this[int position]
{
get
{
// NOTE: we are not validating position here as that would not
// add any value to the range check that string accessor performs anyways.
return _source[position];
}
}
/// <summary>
/// Provides a string representation of the StringText located within given span.
/// </summary>
/// <exception cref="ArgumentOutOfRangeException">When given span is outside of the text range.</exception>
public override string ToString(TextSpan span)
{
if (span.End > this.Source.Length)
{
throw new ArgumentOutOfRangeException("span");
}
if (span.Start == 0 && span.Length == this.Length)
{
return this.Source;
}
else
{
return this.Source.Substring(span.Start, span.Length);
}
}
public override void CopyTo(int sourceIndex, char[] destination, int destinationIndex, int count)
{
this.Source.CopyTo(sourceIndex, destination, destinationIndex, count);
}
public override void Write(TextWriter textWriter, TextSpan span, CancellationToken cancellationToken = default(CancellationToken))
{
if (span.Start == 0 && span.End == this.Length)
{
textWriter.Write(this.Source);
}
else
{
base.Write(textWriter, span, cancellationToken);
}
}
#region Encoding Detection
/// <summary>
/// Check for occurrence of two consecutive NUL (U+0000) characters.
/// This is unlikely to appear in genuine text, so it's a good heuristic
/// to detect binary files.
/// </summary>
/// <remarks>
/// internal for unit testing
/// </remarks>
internal static bool IsBinary(string text)
{
// PERF: We can advance two chars at a time unless we find a NUL.
for (int i = 1; i < text.Length;)
{
if (text[i] == '\0')
{
if (text[i - 1] == '\0')
{
return true;
}
i += 1;
}
else
{
i += 2;
}
}
return false;
}
/// <summary>
/// Try to create a <see cref="EncodedStringText"/> from the given stream using the given encoding.
/// Try to create a <see cref="SourceText"/> from the given stream using the given encoding.
/// </summary>
/// <param name="data">The input stream containing the encoded text. The stream will not be closed.</param>
/// <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>
/// <returns>The <see cref="EncodedStringText"/> decoded from the stream.</returns>
/// <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)
{
data.Seek(0, SeekOrigin.Begin);
if (data.Length > LargeObjectHeapLimit)
{
return LargeEncodedText.Decode(data, encoding, checksumAlgorithm, throwIfBinaryDetected);
}
Encoding actualEncoding;
ImmutableArray<byte> checksum = default(ImmutableArray<byte>);
string text;
Debug.Assert(data != null);
Debug.Assert(encoding != null);
byte[] buffer = TryGetByteArrayFromStream(data);
if (buffer != null)
{
text = Decode(buffer, (int)data.Length, encoding, out actualEncoding);
data.Seek(0, SeekOrigin.Begin);
// Since we have the buffer, compute the checksum here. This saves allocations if we later
// need to write out debugging information.
checksum = CalculateChecksum(buffer, offset: 0, count: (int)data.Length, algorithmId: checksumAlgorithm);
}
else
// For small streams, see if we can read the byte buffer directly.
if (encoding.GetMaxCharCount((int)data.Length) < LargeObjectHeapLimitInChars)
{
text = Decode(data, encoding, out actualEncoding);
byte[] buffer = TryGetByteArrayFromStream(data);
if (buffer != null)
{
return SourceText.From(buffer, (int)data.Length, encoding, checksumAlgorithm, throwIfBinaryDetected);
}
}
return new EncodedStringText(text, actualEncoding, checksum, checksumAlgorithm, throwIfBinary: throwIfBinaryDetected);
return SourceText.From(data, encoding, checksumAlgorithm, throwIfBinaryDetected);
}
/// <summary>
......@@ -265,40 +126,6 @@ private static byte[] TryGetByteArrayFromStream(Stream data)
return null;
}
/// <summary>
/// Decode the given stream using the given encoding. Does not
/// close the stream afterwards.
/// </summary>
/// <param name="data">Data stream</param>
/// <param name="encoding">Default encoding to use for decoding.</param>
/// <param name="actualEncoding">Actual encoding used to read the text.</param>
/// <exception cref="DecoderFallbackException">If the given encoding is set to use <see cref="DecoderExceptionFallback"/> as its fallback decoder.</exception>
/// <returns>Decoded stream as a text string</returns>
private static string Decode(Stream data, Encoding encoding, out Encoding actualEncoding)
{
data.Seek(0, SeekOrigin.Begin);
int length = (int)data.Length;
if (length == 0)
{
actualEncoding = encoding;
return string.Empty;
}
// Note: We are setting the buffer size to 4KB instead of the default 1KB. That's
// because we can reach this code path for FileStreams that are larger than 80KB
// and, to avoid FileStream buffer allocations for small files, we may intentionally
// be using a FileStream with a very small (1 byte) buffer. Using 4KB here matches
// the default buffer size for FileStream and means we'll still be doing file I/O
// in 4KB chunks.
using (var reader = new StreamReader(data, encoding, detectEncodingFromByteOrderMarks: true, bufferSize: Math.Min(4096, length), leaveOpen: true))
{
string text = reader.ReadToEnd();
actualEncoding = reader.CurrentEncoding;
return text;
}
}
/// <summary>
/// If the MemoryStream was created with publiclyVisible=true, then we can access its buffer
/// directly and save allocations in StreamReader. The input MemoryStream is not closed on exit.
......@@ -353,117 +180,5 @@ private static bool TryGetByteArrayFromFileStream(FileStream stream, out byte[]
// line compiler actually specifies a very small buffer size.
return stream.Read(buffer, 0, length) == length;
}
/// <summary>
/// Decode text from a byte array.
/// </summary>
/// <param name="buffer">The byte array containing encoded text.</param>
/// <param name="length">The count of valid bytes in <paramref name="buffer"/>.</param>
/// <param name="encoding">The encoding to use if an encoding cannot be determined from the byte order mark.</param>
/// <param name="actualEncoding">The actual encoding used.</param>
/// <returns>The decoded text.</returns>
/// <exception cref="DecoderFallbackException">If the given encoding is set to use <see cref="DecoderExceptionFallback"/>
/// as its fallback decoder.</exception>
private static string Decode(byte[] buffer, int length, Encoding encoding, out Encoding actualEncoding)
{
int preambleLength;
actualEncoding = TryReadByteOrderMark(buffer, length, out preambleLength) ?? encoding;
return actualEncoding.GetString(buffer, preambleLength, length - preambleLength);
}
/// <summary>
/// Detect an encoding by looking for byte order marks.
/// </summary>
/// <param name="source">A buffer containing the encoded text.</param>
/// <param name="length">The length of valid data in the buffer.</param>
/// <param name="preambleLength">The length of any detected byte order marks.</param>
/// <returns>The detected encoding or null if no recognized byte order mark was present.</returns>
private static Encoding TryReadByteOrderMark(byte[] source, int length, out int preambleLength)
{
Debug.Assert(source != null);
Debug.Assert(length <= source.Length);
if (length >= 2)
{
switch (source[0])
{
case 0xFE:
if (source[1] == 0xFF)
{
preambleLength = 2;
return Encoding.BigEndianUnicode;
}
break;
case 0xFF:
if (source[1] == 0xFE)
{
preambleLength = 2;
return Encoding.Unicode;
}
break;
case 0xEF:
if (source[1] == 0xBB && length >= 3 && source[2] == 0xBF)
{
preambleLength = 3;
return Encoding.UTF8;
}
break;
}
}
preambleLength = 0;
return null;
}
[ThreadStatic]
private static byte[] t_bomBytes;
/// <summary>
/// Detect an encoding by looking for byte order marks at the beginning of the stream.
/// </summary>
/// <param name="data">The stream containing encoded text.</param>
/// <returns>The detected encoding or null if no recognized byte order mark was present.</returns>
/// <remarks>
/// On exit, the stream's position is set to the first position after any decoded byte order
/// mark or rewound to the start if no byte order mark was detected.
/// </remarks>
internal static Encoding TryReadByteOrderMark(Stream data)
{
Debug.Assert(data != null);
data.Seek(0, SeekOrigin.Begin);
if (data.Length < 2)
{
// Not long enough for any valid BOM prefix
return null;
}
// PERF: Avoid repeated calls to Stream.ReadByte since that method allocates a 1-byte array on each call.
// Instead, using a thread local byte array.
if (t_bomBytes == null)
{
t_bomBytes = new byte[3];
}
int validLength = Math.Min((int)data.Length, t_bomBytes.Length);
data.Read(t_bomBytes, 0, validLength);
int preambleLength;
Encoding detectedEncoding = TryReadByteOrderMark(t_bomBytes, validLength, out preambleLength);
if (preambleLength != validLength)
{
data.Seek(preambleLength, SeekOrigin.Begin);
}
return detectedEncoding;
}
#endregion
}
}
......@@ -94,6 +94,7 @@
<Compile Include="Collections\ArrayBuilderExtensions.cs" />
<Compile Include="Collections\ArrayElement.cs" />
<Compile Include="Collections\BitArray.cs" />
<Compile Include="Collections\Boxes.cs" />
<Compile Include="Collections\ByteSequenceComparer.cs" />
<Compile Include="Collections\CachingDictionary.cs" />
<Compile Include="Collections\CachingFactory.cs" />
......@@ -561,6 +562,7 @@
<Compile Include="Syntax\TranslationSyntaxReference.cs" />
<Compile Include="Text\ChangedText.cs" />
<Compile Include="Text\CompositeText.cs" />
<Compile Include="Text\LargeEncodedText.cs" />
<Compile Include="Text\LinePosition.cs" />
<Compile Include="Text\LinePositionSpan.cs" />
<Compile Include="Text\SourceHashAlgorithm.cs" />
......@@ -663,4 +665,4 @@
<Import Project="..\..\..\..\build\VSL.Imports.Closed.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
</ImportGroup>
</Project>
</Project>
\ No newline at end of file
// 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;
namespace Microsoft.CodeAnalysis
{
internal static class Boxes
{
public static readonly object BoxedTrue = true;
public static readonly object BoxedFalse = false;
public static readonly object BoxedByteZero = (byte)0;
public static readonly object BoxedSByteZero = (sbyte)0;
public static readonly object BoxedInt16Zero = (short)0;
public static readonly object BoxedUInt16Zero = (ushort)0;
public static readonly object BoxedInt32Zero = 0;
public static readonly object BoxedInt32One = 1;
public static readonly object BoxedUInt32Zero = 0U;
public static readonly object BoxedInt64Zero = 0L;
public static readonly object BoxedUInt64Zero = 0UL;
public static readonly object BoxedSingleZero = 0.0f;
public static readonly object BoxedDoubleZero = 0.0;
public static readonly object BoxedDecimalZero = 0m;
private static readonly object[] s_boxedAsciiChars = new object[128];
public static object Box(bool b)
{
return b ? BoxedTrue : BoxedFalse;
}
public static object Box(byte b)
{
return b == 0 ? BoxedByteZero : b;
}
public static object Box(sbyte sb)
{
return sb == 0 ? BoxedSByteZero : sb;
}
public static object Box(short s)
{
return s == 0 ? BoxedInt16Zero : s;
}
public static object Box(ushort us)
{
return us == 0 ? BoxedUInt16Zero : us;
}
public static object Box(int i)
{
switch (i)
{
case 0: return BoxedInt32Zero;
case 1: return BoxedInt32One;
default: return i;
}
}
public static object Box(uint u)
{
return u == 0 ? BoxedUInt32Zero : u;
}
public static object Box(long l)
{
return l == 0 ? BoxedInt64Zero : l;
}
public static object Box(ulong ul)
{
return ul == 0 ? BoxedUInt64Zero : ul;
}
public static unsafe object Box(float f)
{
// There are many representations of zero in floating point.
// Use the boxed value only if the bit pattern is all zeros.
return *(int*)(&f) == 0 ? BoxedSingleZero : f;
}
public static object Box(double d)
{
// There are many representations of zero in floating point.
// Use the boxed value only if the bit pattern is all zeros.
return BitConverter.DoubleToInt64Bits(d) == 0 ? BoxedDoubleZero : d;
}
public static object Box(char c)
{
return c < 128
? s_boxedAsciiChars[c] ?? (s_boxedAsciiChars[c] = c)
: c;
}
public static unsafe object Box(decimal d)
{
// There are many representation of zero in System.Decimal
// Use the boxed value only if the bit pattern is all zeros.
ulong* ptr = (ulong*)&d;
return ptr[0] == 0 && ptr[1] == 0 ? BoxedDecimalZero : d;
}
}
}
......@@ -160,15 +160,15 @@ public Compilation Clone()
/// Gets a new <see cref="SemanticModel"/> for the specified syntax tree.
/// </summary>
/// <param name="syntaxTree">The specificed syntax tree.</param>
/// <param name="suppressAccessChecks">
/// <param name="ignoreAccessibility">
/// True if the SemanticModel should ignore accessibility rules when answering semantic questions.
/// </param>
public SemanticModel GetSemanticModel(SyntaxTree syntaxTree, bool suppressAccessChecks = false)
public SemanticModel GetSemanticModel(SyntaxTree syntaxTree, bool ignoreAccessibility = false)
{
return CommonGetSemanticModel(syntaxTree, suppressAccessChecks);
return CommonGetSemanticModel(syntaxTree, ignoreAccessibility);
}
protected abstract SemanticModel CommonGetSemanticModel(SyntaxTree syntaxTree, bool suppressAccessChecks);
protected abstract SemanticModel CommonGetSemanticModel(SyntaxTree syntaxTree, bool ignoreAccessibility);
/// <summary>
/// Returns a new INamedTypeSymbol representing an error type with the given name and arity
......
......@@ -65,7 +65,7 @@ public SyntaxTree SyntaxTree
/// <summary>
/// Returns true if this is a SemanticModel that ignores accessibility rules when answering semantic questions.
/// </summary>
public virtual bool HasAccessChecksSuppressed
public virtual bool IgnoresAccessibility
{
get { return false; }
}
......
......@@ -2,7 +2,6 @@
using System;
using System.Diagnostics;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis
......@@ -437,19 +436,19 @@ public object Value
{
case ConstantValueTypeDiscriminator.Bad: return null;
case ConstantValueTypeDiscriminator.Null: return null;
case ConstantValueTypeDiscriminator.SByte: return SByteValue;
case ConstantValueTypeDiscriminator.Byte: return ByteValue;
case ConstantValueTypeDiscriminator.Int16: return Int16Value;
case ConstantValueTypeDiscriminator.UInt16: return UInt16Value;
case ConstantValueTypeDiscriminator.Int32: return Int32Value;
case ConstantValueTypeDiscriminator.UInt32: return UInt32Value;
case ConstantValueTypeDiscriminator.Int64: return Int64Value;
case ConstantValueTypeDiscriminator.UInt64: return UInt64Value;
case ConstantValueTypeDiscriminator.Char: return CharValue;
case ConstantValueTypeDiscriminator.Boolean: return BooleanValue;
case ConstantValueTypeDiscriminator.Single: return SingleValue;
case ConstantValueTypeDiscriminator.Double: return DoubleValue;
case ConstantValueTypeDiscriminator.Decimal: return DecimalValue;
case ConstantValueTypeDiscriminator.SByte: return Boxes.Box(SByteValue);
case ConstantValueTypeDiscriminator.Byte: return Boxes.Box(ByteValue);
case ConstantValueTypeDiscriminator.Int16: return Boxes.Box(Int16Value);
case ConstantValueTypeDiscriminator.UInt16: return Boxes.Box(UInt16Value);
case ConstantValueTypeDiscriminator.Int32: return Boxes.Box(Int32Value);
case ConstantValueTypeDiscriminator.UInt32: return Boxes.Box(UInt32Value);
case ConstantValueTypeDiscriminator.Int64: return Boxes.Box(Int64Value);
case ConstantValueTypeDiscriminator.UInt64: return Boxes.Box(UInt64Value);
case ConstantValueTypeDiscriminator.Char: return Boxes.Box(CharValue);
case ConstantValueTypeDiscriminator.Boolean: return Boxes.Box(BooleanValue);
case ConstantValueTypeDiscriminator.Single: return Boxes.Box(SingleValue);
case ConstantValueTypeDiscriminator.Double: return Boxes.Box(DoubleValue);
case ConstantValueTypeDiscriminator.Decimal: return Boxes.Box(DecimalValue);
case ConstantValueTypeDiscriminator.DateTime: return DateTimeValue;
case ConstantValueTypeDiscriminator.String: return StringValue;
default: throw ExceptionUtilities.UnexpectedValue(this.Discriminator);
......
......@@ -1936,12 +1936,9 @@ private TypedConstant CreateTypedConstant(TypeSymbol type, TypedConstantKind kin
return new TypedConstant(type, kind, value);
}
private readonly static object s_boxedTrue = true;
private readonly static object s_boxedFalse = false;
private TypedConstant CreateTypedConstant(TypeSymbol type, TypedConstantKind kind, bool value)
{
return CreateTypedConstant(type, kind, value ? s_boxedTrue : s_boxedFalse);
return CreateTypedConstant(type, kind, Boxes.Box(value));
}
/// <summary>
......
......@@ -117,7 +117,7 @@ Microsoft.CodeAnalysis.Compilation.GetAssemblyOrModuleSymbol(Microsoft.CodeAnaly
Microsoft.CodeAnalysis.Compilation.GetCompilationNamespace(Microsoft.CodeAnalysis.INamespaceSymbol namespaceSymbol)
Microsoft.CodeAnalysis.Compilation.GetEntryPoint(System.Threading.CancellationToken cancellationToken)
Microsoft.CodeAnalysis.Compilation.GetMetadataReference(Microsoft.CodeAnalysis.IAssemblySymbol assemblySymbol)
Microsoft.CodeAnalysis.Compilation.GetSemanticModel(Microsoft.CodeAnalysis.SyntaxTree syntaxTree, bool suppressAccessChecks = false)
Microsoft.CodeAnalysis.Compilation.GetSemanticModel(Microsoft.CodeAnalysis.SyntaxTree syntaxTree, bool ignoreAccessibility = false)
Microsoft.CodeAnalysis.Compilation.GetSpecialType(Microsoft.CodeAnalysis.SpecialType specialType)
Microsoft.CodeAnalysis.Compilation.GetSubmissionResultType(out bool hasValue)
Microsoft.CodeAnalysis.Compilation.GetTypeByMetadataName(string fullyQualifiedMetadataName)
......@@ -1327,6 +1327,7 @@ Microsoft.CodeAnalysis.Text.SourceText
Microsoft.CodeAnalysis.Text.SourceText.ChecksumAlgorithm.get
Microsoft.CodeAnalysis.Text.SourceText.ContentEquals(Microsoft.CodeAnalysis.Text.SourceText other)
Microsoft.CodeAnalysis.Text.SourceText.GetSubText(int start)
Microsoft.CodeAnalysis.Text.SourceText.Lines.get
Microsoft.CodeAnalysis.Text.SourceText.Replace(Microsoft.CodeAnalysis.Text.TextSpan span, string newText)
Microsoft.CodeAnalysis.Text.SourceText.Replace(int start, int length, string newText)
Microsoft.CodeAnalysis.Text.SourceText.SourceText(System.Collections.Immutable.ImmutableArray<byte> checksum = default(System.Collections.Immutable.ImmutableArray<byte>), Microsoft.CodeAnalysis.Text.SourceHashAlgorithm checksumAlgorithm = Microsoft.CodeAnalysis.Text.SourceHashAlgorithm.Sha1, Microsoft.CodeAnalysis.Text.SourceTextContainer container = null)
......@@ -1448,7 +1449,7 @@ abstract Microsoft.CodeAnalysis.Compilation.CommonGetAssemblyOrModuleSymbol(Micr
abstract Microsoft.CodeAnalysis.Compilation.CommonGetCompilationNamespace(Microsoft.CodeAnalysis.INamespaceSymbol namespaceSymbol)
abstract Microsoft.CodeAnalysis.Compilation.CommonGetEntryPoint(System.Threading.CancellationToken cancellationToken)
abstract Microsoft.CodeAnalysis.Compilation.CommonGetMetadataReference(Microsoft.CodeAnalysis.IAssemblySymbol assemblySymbol)
abstract Microsoft.CodeAnalysis.Compilation.CommonGetSemanticModel(Microsoft.CodeAnalysis.SyntaxTree syntaxTree, bool suppressAccessChecks)
abstract Microsoft.CodeAnalysis.Compilation.CommonGetSemanticModel(Microsoft.CodeAnalysis.SyntaxTree syntaxTree, bool ignoreAccessibility)
abstract Microsoft.CodeAnalysis.Compilation.CommonGetSpecialType(Microsoft.CodeAnalysis.SpecialType specialType)
abstract Microsoft.CodeAnalysis.Compilation.CommonGetSubmissionResultType(out bool hasValue)
abstract Microsoft.CodeAnalysis.Compilation.CommonGetTypeByMetadataName(string metadataName)
......@@ -2016,7 +2017,8 @@ static Microsoft.CodeAnalysis.Text.LinePosition.operator >=(Microsoft.CodeAnalys
static Microsoft.CodeAnalysis.Text.LinePositionSpan.operator !=(Microsoft.CodeAnalysis.Text.LinePositionSpan left, Microsoft.CodeAnalysis.Text.LinePositionSpan right)
static Microsoft.CodeAnalysis.Text.LinePositionSpan.operator ==(Microsoft.CodeAnalysis.Text.LinePositionSpan left, Microsoft.CodeAnalysis.Text.LinePositionSpan right)
static Microsoft.CodeAnalysis.Text.SourceText.CalculateChecksum(byte[] buffer, int offset, int count, Microsoft.CodeAnalysis.Text.SourceHashAlgorithm algorithmId)
static Microsoft.CodeAnalysis.Text.SourceText.From(System.IO.Stream stream, System.Text.Encoding encoding = null, Microsoft.CodeAnalysis.Text.SourceHashAlgorithm checksumAlgorithm = Microsoft.CodeAnalysis.Text.SourceHashAlgorithm.Sha1)
static Microsoft.CodeAnalysis.Text.SourceText.From(byte[] buffer, int length, System.Text.Encoding encoding = null, Microsoft.CodeAnalysis.Text.SourceHashAlgorithm checksumAlgorithm = Microsoft.CodeAnalysis.Text.SourceHashAlgorithm.Sha1, bool throwIfBinaryDetected = false)
static Microsoft.CodeAnalysis.Text.SourceText.From(System.IO.Stream stream, System.Text.Encoding encoding = null, Microsoft.CodeAnalysis.Text.SourceHashAlgorithm checksumAlgorithm = Microsoft.CodeAnalysis.Text.SourceHashAlgorithm.Sha1, bool throwIfBinaryDetected = false)
static Microsoft.CodeAnalysis.Text.SourceText.From(string text, System.Text.Encoding encoding = null, Microsoft.CodeAnalysis.Text.SourceHashAlgorithm checksumAlgorithm = Microsoft.CodeAnalysis.Text.SourceHashAlgorithm.Sha1)
static Microsoft.CodeAnalysis.Text.TextChange.implicit operator Microsoft.CodeAnalysis.Text.TextChangeRange(Microsoft.CodeAnalysis.Text.TextChange change)
static Microsoft.CodeAnalysis.Text.TextChange.operator !=(Microsoft.CodeAnalysis.Text.TextChange left, Microsoft.CodeAnalysis.Text.TextChange right)
......@@ -2065,8 +2067,8 @@ virtual Microsoft.CodeAnalysis.Location.MetadataModule.get
virtual Microsoft.CodeAnalysis.Location.SourceSpan.get
virtual Microsoft.CodeAnalysis.Location.SourceTree.get
virtual Microsoft.CodeAnalysis.MetadataReference.Display.get
virtual Microsoft.CodeAnalysis.SemanticModel.IgnoresAccessibility.get
virtual Microsoft.CodeAnalysis.SemanticModel.GetTopmostNodeForDiagnosticAnalysis(Microsoft.CodeAnalysis.ISymbol symbol, Microsoft.CodeAnalysis.SyntaxNode declaringSyntax)
virtual Microsoft.CodeAnalysis.SemanticModel.HasAccessChecksSuppressed.get
virtual Microsoft.CodeAnalysis.SymbolVisitor.DefaultVisit(Microsoft.CodeAnalysis.ISymbol symbol)
virtual Microsoft.CodeAnalysis.SymbolVisitor.Visit(Microsoft.CodeAnalysis.ISymbol symbol)
virtual Microsoft.CodeAnalysis.SymbolVisitor.VisitAlias(Microsoft.CodeAnalysis.IAliasSymbol symbol)
......@@ -2115,9 +2117,9 @@ virtual Microsoft.CodeAnalysis.SyntaxWalker.VisitTrivia(Microsoft.CodeAnalysis.S
virtual Microsoft.CodeAnalysis.Text.SourceText.Container.get
virtual Microsoft.CodeAnalysis.Text.SourceText.ContentEqualsImpl(Microsoft.CodeAnalysis.Text.SourceText other)
virtual Microsoft.CodeAnalysis.Text.SourceText.GetChangeRanges(Microsoft.CodeAnalysis.Text.SourceText oldText)
virtual Microsoft.CodeAnalysis.Text.SourceText.GetLinesCore()
virtual Microsoft.CodeAnalysis.Text.SourceText.GetSubText(Microsoft.CodeAnalysis.Text.TextSpan span)
virtual Microsoft.CodeAnalysis.Text.SourceText.GetTextChanges(Microsoft.CodeAnalysis.Text.SourceText oldText)
virtual Microsoft.CodeAnalysis.Text.SourceText.Lines.get
virtual Microsoft.CodeAnalysis.Text.SourceText.ToString(Microsoft.CodeAnalysis.Text.TextSpan span)
virtual Microsoft.CodeAnalysis.Text.SourceText.WithChanges(System.Collections.Generic.IEnumerable<Microsoft.CodeAnalysis.Text.TextChange> changes)
virtual Microsoft.CodeAnalysis.Text.SourceText.Write(System.IO.TextWriter writer, Microsoft.CodeAnalysis.Text.TextSpan span, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken))
......
......@@ -4,6 +4,7 @@
using System.Diagnostics;
using System.IO;
using System.Text;
using Microsoft.CodeAnalysis;
namespace Roslyn.Utilities
{
......@@ -181,10 +182,6 @@ public uint ReadCompressedUInt()
}
}
private static readonly object s_int32Zero = 0;
private static readonly object s_booleanTrue = true;
private static readonly object s_booleanFalse = false;
/// <summary>
/// Read a value from the stream. The value must have been written using ObjectWriter.WriteValue.
/// </summary>
......@@ -196,9 +193,9 @@ public object ReadValue()
case DataKind.Null:
return null;
case DataKind.Boolean_T:
return s_booleanTrue;
return Boxes.BoxedTrue;
case DataKind.Boolean_F:
return s_booleanFalse;
return Boxes.BoxedFalse;
case DataKind.Int8:
return _reader.ReadSByte();
case DataKind.UInt8:
......@@ -214,7 +211,7 @@ public object ReadValue()
case DataKind.Int32_S:
return (int)_reader.ReadUInt16();
case DataKind.Int32_Z:
return s_int32Zero;
return Boxes.BoxedInt32Zero;
case DataKind.UInt32:
return _reader.ReadUInt32();
case DataKind.Int64:
......
using System;
// 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;
using System.Collections.Immutable;
using System.IO;
using System.Text;
......@@ -123,21 +125,9 @@ private int GetIndexFromPosition(int position)
}
}
public override Encoding Encoding
{
get
{
return _encoding;
}
}
public override Encoding Encoding => _encoding;
public override int Length
{
get
{
return _length;
}
}
public override int Length => _length;
public override void CopyTo(int sourceIndex, char[] destination, int destinationIndex, int count)
{
......@@ -196,5 +186,70 @@ public override void Write(TextWriter writer, TextSpan span, CancellationToken c
chunkIndex++;
}
}
/// <summary>
/// Called from <see cref="SourceText.Lines"/> to initialize the <see cref="TextLineCollection"/>. Thereafter,
/// the collection is cached.
/// </summary>
/// <returns>A new <see cref="TextLineCollection"/> representing the individual text lines.</returns>
protected override TextLineCollection GetLinesCore()
{
return new LineInfo(this, ParseLineStarts());
}
private int[] ParseLineStarts()
{
var position = 0;
var index = 0;
var lastCr = -1;
var arrayBuilder = ArrayBuilder<int>.GetInstance();
// The following loop goes through every character in the text. It is highly
// performance critical, and thus inlines knowledge about common line breaks
// and non-line breaks.
foreach (var chunk in _chunks)
{
foreach (var c in chunk)
{
index++;
// Common case - ASCII & not a line break
const uint bias = '\r' + 1;
if (unchecked(c - bias) <= (127 - bias))
{
continue;
}
switch(c)
{
case '\r':
lastCr = index;
goto line_break;
case '\n':
// Assumes that the only 2-char line break sequence is CR+LF
if (lastCr == (index - 1))
{
position = index;
break;
}
goto line_break;
case '\u0085':
case '\u2028':
case '\u2029':
line_break:
arrayBuilder.Add(position);
position = index;
break;
}
}
}
// Create a start for the final line.
arrayBuilder.Add(position);
return arrayBuilder.ToArrayAndFree();
}
}
}
......@@ -6,7 +6,6 @@
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using Roslyn.Utilities;
......@@ -20,14 +19,17 @@ public abstract class SourceText
{
private const int CharBufferSize = 32 * 1024;
private const int CharBufferCount = 5;
private const int LargeObjectHeapLimitInChars = 40 * 1024; // 40KB
private static readonly ObjectPool<char[]> s_charArrayPool = new ObjectPool<char[]>(() => new char[CharBufferSize], CharBufferCount);
private readonly SourceHashAlgorithm _checksumAlgorithm;
private SourceTextContainer _lazyContainer;
private LineInfo _lazyLineInfo;
private TextLineCollection _lazyLineInfo;
private ImmutableArray<byte> _lazyChecksum;
private static readonly Encoding Utf8EncodingWithNoBOM = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: false);
protected SourceText(ImmutableArray<byte> checksum = default(ImmutableArray<byte>), SourceHashAlgorithm checksumAlgorithm = SourceHashAlgorithm.Sha1, SourceTextContainer container = null)
{
ValidateChecksumAlgorithm(checksumAlgorithm);
......@@ -78,7 +80,7 @@ public static SourceText From(string text, Encoding encoding = null, SourceHashA
/// <summary>
/// Constructs a <see cref="SourceText"/> from stream content.
/// </summary>
/// <param name="stream">Stream.</param>
/// <param name="stream">Stream. The stream must be seekable.</param>
/// <param name="encoding">
/// Data encoding to use if the stream doesn't start with Byte Order Mark specifying the encoding.
/// <see cref="Encoding.UTF8"/> if not specified.
......@@ -86,14 +88,18 @@ public static SourceText From(string text, Encoding encoding = null, SourceHashA
/// <param name="checksumAlgorithm">
/// Hash algorithm to use to calculate checksum of the text that's saved to PDB.
/// </param>
/// <param name="throwIfBinaryDetected">If the decoded text contains at least two consecutive NUL
/// characters, then an <see cref="InvalidDataException"/> is thrown.</param>
/// <exception cref="ArgumentNullException"><paramref name="stream"/> is null.</exception>
/// <exception cref="ArgumentException">
/// <paramref name="stream"/> doesn't support reading or seeking.
/// <paramref name="checksumAlgorithm"/> is not supported.
/// </exception>
/// <exception cref="DecoderFallbackException">If the given encoding is set to use a throwing decoder as a fallback</exception>
/// <exception cref="InvalidDataException">Two consecutive NUL characters were detected in the decoded text and <paramref name="throwIfBinaryDetected"/> was true.</exception>
/// <exception cref="IOException">An I/O error occurs.</exception>
/// <remarks>Reads from the beginning of the stream. Leaves the stream open.</remarks>
public static SourceText From(Stream stream, Encoding encoding = null, SourceHashAlgorithm checksumAlgorithm = SourceHashAlgorithm.Sha1)
public static SourceText From(Stream stream, Encoding encoding = null, SourceHashAlgorithm checksumAlgorithm = SourceHashAlgorithm.Sha1, bool throwIfBinaryDetected = false)
{
if (stream == null)
{
......@@ -107,29 +113,158 @@ public static SourceText From(Stream stream, Encoding encoding = null, SourceHas
ValidateChecksumAlgorithm(checksumAlgorithm);
encoding = encoding ?? Encoding.UTF8;
encoding = encoding ?? Utf8EncodingWithNoBOM;
// TODO: unify encoding detection with EncodedStringText
// If the resulting string would end up on the large object heap, then use LargeEncodedText.
if (encoding.GetMaxCharCount((int)stream.Length) >= LargeObjectHeapLimitInChars)
{
return LargeEncodedText.Decode(stream, encoding, checksumAlgorithm, throwIfBinaryDetected);
}
stream.Seek(0, SeekOrigin.Begin);
string text;
using (var reader = new StreamReader(stream, encoding, detectEncodingFromByteOrderMarks: true, bufferSize: 1024, leaveOpen: true))
string text = Decode(stream, encoding, out encoding);
if (throwIfBinaryDetected && IsBinary(text))
{
text = reader.ReadToEnd();
encoding = reader.CurrentEncoding;
throw new InvalidDataException();
}
return new StringText(text, encoding, CalculateChecksum(stream, checksumAlgorithm), checksumAlgorithm);
var checksum = CalculateChecksum(stream, checksumAlgorithm);
return new StringText(text, encoding, checksum, checksumAlgorithm);
}
/// <summary>
/// Constructs a <see cref="SourceText"/> from a byte array.
/// </summary>
/// <param name="buffer">The encoded source buffer.</param>
/// <param name="length">The number of bytes to read from the buffer.</param>
/// <param name="encoding">
/// Data encoding to use if the encoded buffer doesn't start with Byte Order Mark.
/// <see cref="Encoding.UTF8"/> if not specified.
/// </param>
/// <param name="checksumAlgorithm">
/// Hash algorithm to use to calculate checksum of the text that's saved to PDB.
/// </param>
/// <param name="throwIfBinaryDetected">If the decoded text contains at least two consecutive NUL
/// characters, then an <see cref="InvalidDataException"/> is thrown.</param>
/// <returns>The decoded text.</returns>
/// <exception cref="ArgumentNullException">The <paramref name="buffer"/> is null.</exception>
/// <exception cref="ArgumentOutOfRangeException">The <paramref name="length"/> is negative or longer than the <paramref name="buffer"/>.</exception>
/// <exception cref="ArgumentException"><paramref name="checksumAlgorithm"/> is not supported.</exception>
/// <exception cref="DecoderFallbackException">If the given encoding is set to use a throwing decoder as a fallback</exception>
/// <exception cref="InvalidDataException">Two consecutive NUL characters were detected in the decoded text and <paramref name="throwIfBinaryDetected"/> was true.</exception>
public static SourceText From(byte[] buffer, int length, Encoding encoding = null, SourceHashAlgorithm checksumAlgorithm = SourceHashAlgorithm.Sha1, bool throwIfBinaryDetected = false)
{
if (buffer == null)
{
throw new ArgumentNullException(nameof(buffer));
}
if (length < 0 || length > buffer.Length)
{
throw new ArgumentOutOfRangeException(nameof(length));
}
ValidateChecksumAlgorithm(checksumAlgorithm);
string text = Decode(buffer, length, encoding ?? Utf8EncodingWithNoBOM, out encoding);
if (throwIfBinaryDetected && IsBinary(text))
{
throw new InvalidDataException();
}
// Since we have the bytes in hand, it's easy to compute the checksum.
var checksum = CalculateChecksum(buffer, 0, length, checksumAlgorithm);
return new StringText(text, encoding, checksum, checksumAlgorithm);
}
/// <summary>
/// Decode text from a stream.
/// </summary>
/// <param name="stream">The stream containing encoded text.</param>
/// <param name="encoding">The encoding to use if an encoding cannot be determined from the byte order mark.</param>
/// <param name="actualEncoding">The actual encoding used.</param>
/// <returns>The decoded text.</returns>
/// <exception cref="DecoderFallbackException">If the given encoding is set to use a throwing decoder as a fallback</exception>
private static string Decode(Stream stream, Encoding encoding, out Encoding actualEncoding)
{
Debug.Assert(stream != null);
Debug.Assert(encoding != null);
stream.Seek(0, SeekOrigin.Begin);
int length = (int)stream.Length;
if (length == 0)
{
actualEncoding = encoding;
return string.Empty;
}
// Note: We are setting the buffer size to 4KB instead of the default 1KB. That's
// because we can reach this code path for FileStreams and, to avoid FileStream
// buffer allocations for small files, we may intentionally be using a FileStream
// with a very small (1 byte) buffer. Using 4KB here matches the default buffer
// size for FileStream and means we'll still be doing file I/O in 4KB chunks.
using (var reader = new StreamReader(stream, encoding, detectEncodingFromByteOrderMarks: true, bufferSize: Math.Min(4096, length), leaveOpen: true))
{
string text = reader.ReadToEnd();
actualEncoding = reader.CurrentEncoding;
return text;
}
}
/// <summary>
/// Decode text from a byte array.
/// </summary>
public SourceHashAlgorithm ChecksumAlgorithm
/// <param name="buffer">The byte array containing encoded text.</param>
/// <param name="length">The count of valid bytes in <paramref name="buffer"/>.</param>
/// <param name="encoding">The encoding to use if an encoding cannot be determined from the byte order mark.</param>
/// <param name="actualEncoding">The actual encoding used.</param>
/// <returns>The decoded text.</returns>
/// <exception cref="DecoderFallbackException">If the given encoding is set to use a throwing decoder as a fallback</exception>
private static string Decode(byte[] buffer, int length, Encoding encoding, out Encoding actualEncoding)
{
get { return _checksumAlgorithm; }
Debug.Assert(buffer != null);
Debug.Assert(encoding != null);
int preambleLength;
actualEncoding = TryReadByteOrderMark(buffer, length, out preambleLength) ?? encoding;
return actualEncoding.GetString(buffer, preambleLength, length - preambleLength);
}
/// <summary>
/// Check for occurrence of two consecutive NUL (U+0000) characters.
/// This is unlikely to appear in genuine text, so it's a good heuristic
/// to detect binary files.
/// </summary>
/// <remarks>
/// internal for unit testing
/// </remarks>
internal static bool IsBinary(string text)
{
// PERF: We can advance two chars at a time unless we find a NUL.
for (int i = 1; i < text.Length;)
{
if (text[i] == '\0')
{
if (text[i - 1] == '\0')
{
return true;
}
i += 1;
}
else
{
i += 2;
}
}
return false;
}
/// <summary>
/// Hash algorithm to use to calculate checksum of the text that's saved to PDB.
/// </summary>
public SourceHashAlgorithm ChecksumAlgorithm => _checksumAlgorithm;
/// <summary>
/// Encoding of the file that the text was read from or is going to be saved to.
/// <c>null</c> if the encoding is unspecified.
......@@ -479,21 +614,26 @@ public virtual IReadOnlyList<TextChange> GetTextChanges(SourceText oldText)
/// <summary>
/// The collection of individual text lines.
/// </summary>
public virtual TextLineCollection Lines
public TextLineCollection Lines
{
get
{
if (_lazyLineInfo == null)
{
var info = new LineInfo(this, this.ParseLineStarts());
Interlocked.CompareExchange(ref _lazyLineInfo, info, null);
}
return _lazyLineInfo;
var info = _lazyLineInfo;
return info ?? Interlocked.CompareExchange(ref _lazyLineInfo, info = GetLinesCore(), null) ?? info;
}
}
private class LineInfo : TextLineCollection
/// <summary>
/// Called from <see cref="Lines"/> to initialize the <see cref="TextLineCollection"/>. Thereafter,
/// the collection is cached.
/// </summary>
/// <returns>A new <see cref="TextLineCollection"/> representing the individual text lines.</returns>
protected virtual TextLineCollection GetLinesCore()
{
return new LineInfo(this, ParseLineStarts());
}
internal sealed class LineInfo : TextLineCollection
{
private readonly SourceText _text;
private readonly int[] _lineStarts;
......@@ -505,10 +645,7 @@ public LineInfo(SourceText text, int[] lineStarts)
_lineStarts = lineStarts;
}
public override int Count
{
get { return _lineStarts.Length; }
}
public override int Count => _lineStarts.Length;
public override TextLine this[int index]
{
......@@ -701,6 +838,55 @@ protected virtual bool ContentEqualsImpl(SourceText other)
#endregion
/// <summary>
/// Detect an encoding by looking for byte order marks.
/// </summary>
/// <param name="source">A buffer containing the encoded text.</param>
/// <param name="length">The length of valid data in the buffer.</param>
/// <param name="preambleLength">The length of any detected byte order marks.</param>
/// <returns>The detected encoding or null if no recognized byte order mark was present.</returns>
internal static Encoding TryReadByteOrderMark(byte[] source, int length, out int preambleLength)
{
Debug.Assert(source != null);
Debug.Assert(length <= source.Length);
if (length >= 2)
{
switch (source[0])
{
case 0xFE:
if (source[1] == 0xFF)
{
preambleLength = 2;
return Encoding.BigEndianUnicode;
}
break;
case 0xFF:
if (source[1] == 0xFE)
{
preambleLength = 2;
return Encoding.Unicode;
}
break;
case 0xEF:
if (source[1] == 0xBB && length >= 3 && source[2] == 0xBF)
{
preambleLength = 3;
return Encoding.UTF8;
}
break;
}
}
preambleLength = 0;
return null;
}
private class StaticContainer : SourceTextContainer
{
private readonly SourceText _text;
......@@ -710,10 +896,7 @@ public StaticContainer(SourceText text)
_text = text;
}
public override SourceText CurrentText
{
get { return _text; }
}
public override SourceText CurrentText => _text;
public override event EventHandler<TextChangeEventArgs> TextChanged
{
......
......@@ -4,10 +4,8 @@
using System.Collections.Immutable;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Text;
using System.Threading;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Text
{
......@@ -28,26 +26,17 @@ internal StringText(string source, Encoding encodingOpt, ImmutableArray<byte> ch
_encodingOpt = encodingOpt;
}
public override Encoding Encoding
{
get { return _encodingOpt; }
}
public override Encoding Encoding => _encodingOpt;
/// <summary>
/// Underlying string which is the source of this <see cref="StringText"/>instance
/// </summary>
public string Source
{
get { return _source; }
}
public string Source => _source;
/// <summary>
/// The length of the text represented by <see cref="StringText"/>.
/// </summary>
public override int Length
{
get { return this.Source.Length; }
}
public override int Length => _source.Length;
/// <summary>
/// Returns a character at given position.
......
......@@ -11,15 +11,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Friend NotInheritable Class AttributeSemanticModel
Inherits MemberSemanticModel
Private Sub New(root As VisualBasicSyntaxNode, binder As Binder, Optional parentSemanticModelOpt As SyntaxTreeSemanticModel = Nothing, Optional speculatedPosition As Integer = 0, Optional isSuppressingAccessChecks As Boolean = False)
MyBase.New(root, binder, parentSemanticModelOpt, speculatedPosition, isSuppressingAccessChecks)
Private Sub New(root As VisualBasicSyntaxNode, binder As Binder, Optional parentSemanticModelOpt As SyntaxTreeSemanticModel = Nothing, Optional speculatedPosition As Integer = 0, Optional ignoreAccessibility As Boolean = False)
MyBase.New(root, binder, parentSemanticModelOpt, speculatedPosition, ignoreAccessibility)
End Sub
''' <summary>
''' Creates an AttributeSemanticModel that allows asking semantic questions about an attribute node.
''' </summary>
Friend Shared Function Create(binder As AttributeBinder, Optional isSuppressingAccessChecks As Boolean = False) As AttributeSemanticModel
Return New AttributeSemanticModel(binder.Root, binder, isSuppressingAccessChecks:=isSuppressingAccessChecks)
Friend Shared Function Create(binder As AttributeBinder, Optional ignoreAccessibility As Boolean = False) As AttributeSemanticModel
Return New AttributeSemanticModel(binder.Root, binder, ignoreAccessibility:=ignoreAccessibility)
End Function
''' <summary>
......
......@@ -10,15 +10,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Friend NotInheritable Class InitializerSemanticModel
Inherits MemberSemanticModel
Private Sub New(root As VisualBasicSyntaxNode, binder As Binder, Optional parentSemanticModelOpt As SyntaxTreeSemanticModel = Nothing, Optional speculatedPosition As Integer = 0, Optional isSuppressingAccessChecks As Boolean = False)
MyBase.New(root, binder, parentSemanticModelOpt, speculatedPosition, isSuppressingAccessChecks)
Private Sub New(root As VisualBasicSyntaxNode, binder As Binder, Optional parentSemanticModelOpt As SyntaxTreeSemanticModel = Nothing, Optional speculatedPosition As Integer = 0, Optional ignoreAccessibility As Boolean = False)
MyBase.New(root, binder, parentSemanticModelOpt, speculatedPosition, ignoreAccessibility)
End Sub
''' <summary>
''' Creates an InitializerSemanticModel that allows asking semantic questions about an initializer node.
''' </summary>
Friend Shared Function Create(binder As DeclarationInitializerBinder, Optional isSuppressingAccessChecks As Boolean = False) As InitializerSemanticModel
Return New InitializerSemanticModel(binder.Root, binder, isSuppressingAccessChecks:=isSuppressingAccessChecks)
Friend Shared Function Create(binder As DeclarationInitializerBinder, Optional ignoreAccessibility As Boolean = False) As InitializerSemanticModel
Return New InitializerSemanticModel(binder.Root, binder, ignoreAccessibility:=ignoreAccessibility)
End Function
''' <summary>
......@@ -102,7 +102,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Else
' get field symbol
Dim fieldSymbol = DirectCast(Me.MemberSymbol, SourceFieldSymbol)
Dim boundInitializers = ArrayBuilder(Of BoundInitializer).GetInstance
Dim boundInitializers = ArrayBuilder(Of boundInitializer).GetInstance
If initializer IsNot Nothing Then
' bind const and non const field initializers the same to get a bound expression back and not a constant value.
binder.BindFieldInitializer(ImmutableArray.Create(Of Symbol)(fieldSymbol), initializer, boundInitializers, diagnostics, bindingForSemanticModel:=True)
......@@ -117,7 +117,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Case SymbolKind.Property
' get property symbol
Dim propertySymbol = DirectCast(Me.MemberSymbol, SourcePropertySymbol)
Dim boundInitializers = ArrayBuilder(Of BoundInitializer).GetInstance
Dim boundInitializers = ArrayBuilder(Of boundInitializer).GetInstance
binder.BindPropertyInitializer(propertySymbol, initializer, boundInitializers, diagnostics)
boundInitializer = boundInitializers.First
boundInitializers.Free()
......
......@@ -22,14 +22,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
' Fields specific to speculative MemberSemanticModel
Private ReadOnly m_parentSemanticModelOpt As SyntaxTreeSemanticModel
Private ReadOnly m_speculatedPosition As Integer
Private ReadOnly m_hasAccessChecksSuppressed As Boolean
Private ReadOnly m_ignoresAccessibility As Boolean
Friend Sub New(root As VisualBasicSyntaxNode, rootBinder As Binder, parentSemanticModelOpt As SyntaxTreeSemanticModel, speculatedPosition As Integer, Optional isSuppressingAccessChecks As Boolean = False)
Friend Sub New(root As VisualBasicSyntaxNode, rootBinder As Binder, parentSemanticModelOpt As SyntaxTreeSemanticModel, speculatedPosition As Integer, Optional ignoreAccessibility As Boolean = False)
Debug.Assert(parentSemanticModelOpt Is Nothing OrElse Not parentSemanticModelOpt.IsSpeculativeSemanticModel, VBResources.ChainingSpeculativeModelIsNotSupported)
m_Root = root
m_hasAccessChecksSuppressed = isSuppressingAccessChecks
m_RootBinder = SemanticModelBinder.Mark(rootBinder, isSuppressingAccessChecks)
m_ignoresAccessibility = ignoreAccessibility
m_RootBinder = SemanticModelBinder.Mark(rootBinder, ignoreAccessibility)
m_parentSemanticModelOpt = parentSemanticModelOpt
m_speculatedPosition = speculatedPosition
End Sub
......@@ -64,22 +64,22 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Get
End Property
Public NotOverridable Overrides ReadOnly Property HasAccessChecksSuppressed As Boolean
Public NotOverridable Overrides ReadOnly Property IgnoresAccessibility As Boolean
Get
Return Me.m_hasAccessChecksSuppressed
Return Me.m_ignoresAccessibility
End Get
End Property
Friend NotOverridable Overloads Overrides Function GetEnclosingBinder(position As Integer) As Binder
Dim binder = GetEnclosingBinderInternal(Me.RootBinder, Me.Root, FindInitialNodeFromPosition(position), position)
Debug.Assert(binder IsNot Nothing)
Return SemanticModelBinder.Mark(binder, HasAccessChecksSuppressed)
Return SemanticModelBinder.Mark(binder, IgnoresAccessibility)
End Function
Private Overloads Function GetEnclosingBinder(node As VisualBasicSyntaxNode) As Binder
Dim binder = GetEnclosingBinderInternal(Me.RootBinder, Me.Root, node, node.SpanStart)
Debug.Assert(binder IsNot Nothing)
Return SemanticModelBinder.Mark(binder, HasAccessChecksSuppressed)
Return SemanticModelBinder.Mark(binder, IgnoresAccessibility)
End Function
' Get the bound node corresponding to the root.
......@@ -97,7 +97,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Dim vbDestination = destination.EnsureVbSymbolOrNothing(Of TypeSymbol)(NameOf(destination))
Dim boundExpression = TryCast(Me.GetLowerBoundNode(expression), BoundExpression)
Dim boundExpression = TryCast(Me.GetLowerBoundNode(expression), boundExpression)
If boundExpression Is Nothing OrElse vbDestination.IsErrorType() Then
Return New Conversion(Nothing) ' NoConversion
......@@ -171,17 +171,17 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return Nothing
End If
Dim expressionSyntax = TryCast(parent, ExpressionSyntax)
Dim expressionSyntax = TryCast(parent, expressionSyntax)
If expressionSyntax IsNot Nothing Then
Return SyntaxFactory.GetStandaloneExpression(expressionSyntax)
End If
Dim statementSyntax = TryCast(parent, StatementSyntax)
Dim statementSyntax = TryCast(parent, statementSyntax)
If statementSyntax IsNot Nothing AndAlso IsStandaloneStatement(statementSyntax) Then
Return statementSyntax
End If
Dim attributeSyntax = TryCast(parent, AttributeSyntax)
Dim attributeSyntax = TryCast(parent, attributeSyntax)
If attributeSyntax IsNot Nothing Then
Return attributeSyntax
End If
......@@ -499,7 +499,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
' We should always be able to get at least an error binding for a lambda, so assert
' if this isn't true.
Dim boundlambda = TryCast(GetLowerBoundNode(lambdaSyntax), BoundLambda)
Dim boundlambda = TryCast(GetLowerBoundNode(lambdaSyntax), boundlambda)
Debug.Assert(boundlambda IsNot Nothing)
If boundlambda IsNot Nothing Then
......@@ -585,7 +585,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Throw New ArgumentException(VBResources.AnonymousObjectCreationExpressionSyntaxNotWithinTree)
End If
Dim boundExpression = TryCast(GetLowerBoundNode(anonymousObjectCreationExpressionSyntax), BoundExpression)
Dim boundExpression = TryCast(GetLowerBoundNode(anonymousObjectCreationExpressionSyntax), boundExpression)
If boundExpression Is Nothing Then
Return Nothing
End If
......@@ -611,7 +611,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return Nothing
End If
Dim boundExpression = TryCast(GetLowerBoundNode(anonymousObjectCreation), BoundExpression)
Dim boundExpression = TryCast(GetLowerBoundNode(anonymousObjectCreation), boundExpression)
If boundExpression Is Nothing Then
Return Nothing
End If
......@@ -728,7 +728,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
' NOTE: What VB calls the current conversion is used to convert the current placeholder to the iteration
' variable type. In the terminology of the public API, this is a conversion from the element type to the
' iteration variable type, and is referred to as the element conversion.
Dim boundConversion = DirectCast(enumeratorInfo.CurrentConversion, BoundConversion)
Dim boundConversion = DirectCast(enumeratorInfo.CurrentConversion, boundConversion)
elementConversion = New Conversion(KeyValuePair.Create(boundConversion.ConversionKind, TryCast(boundConversion.ExpressionSymbol, MethodSymbol)))
End If
......@@ -1011,7 +1011,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Function
Friend NotOverridable Overrides Function TryGetSpeculativeSemanticModelCore(parentModel As SyntaxTreeSemanticModel, position As Integer, type As TypeSyntax, bindingOption As SpeculativeBindingOption, <Out> ByRef speculativeModel As SemanticModel) As Boolean
Dim binder As Binder = Me.GetSpeculativeBinderForExpression(position, type, bindingOption)
Dim binder As binder = Me.GetSpeculativeBinderForExpression(position, type, bindingOption)
If binder Is Nothing Then
speculativeModel = Nothing
Return False
......@@ -1167,7 +1167,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
node As VisualBasicSyntaxNode,
position As Integer
) As Binder
Dim binder As Binder = Nothing
Dim binder As binder = Nothing
EnsureFullyBoundIfImplicitVariablesAllowed()
......@@ -1315,7 +1315,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Function
Private Function GetAggregateClauseLambdaBinder(aggregate As AggregateClauseSyntax, position As Integer) As Binder
Dim binder As Binder = Nothing
Dim binder As binder = Nothing
' If position were in context of an additional query operator that operator would have handled it, unless there were
' no need for a special binder.
......@@ -1324,7 +1324,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
If SyntaxFacts.InSpanOrEffectiveTrailingOfNode(aggregate, position) Then
If Not aggregate.IntoKeyword.IsMissing AndAlso aggregate.IntoKeyword.SpanStart <= position Then
' Should return binder for the Into clause - the last one associated with the node.
Dim binders As ImmutableArray(Of Binder) = GetQueryClauseLambdaBinders(aggregate)
Dim binders As ImmutableArray(Of binder) = GetQueryClauseLambdaBinders(aggregate)
#If DEBUG Then
Debug.Assert(Not binders.IsDefault OrElse Not ShouldHaveFound(aggregate, guard:=True))
Debug.Assert(binders.IsDefault OrElse (binders.Length > 0 AndAlso binders.Length < 3))
......@@ -1345,7 +1345,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
' - Into clause binder.
' If this Aggregate begins the query, it has only one binder - the Into clause binder.
Dim binders As ImmutableArray(Of Binder) = GetQueryClauseLambdaBinders(aggregate)
Dim binders As ImmutableArray(Of binder) = GetQueryClauseLambdaBinders(aggregate)
#If DEBUG Then
Debug.Assert(Not binders.IsDefault OrElse Not ShouldHaveFound(aggregate, guard:=True))
Debug.Assert(binders.IsDefault OrElse (binders.Length > 0 AndAlso binders.Length < 3 AndAlso binders(0) IsNot Nothing))
......@@ -1362,12 +1362,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Private Function GetGroupJoinClauseLambdaBinder(join As GroupJoinClauseSyntax, position As Integer) As Binder
Dim binder As Binder = Nothing
Dim binder As binder = Nothing
If SyntaxFacts.InSpanOrEffectiveTrailingOfNode(join, position) Then
If Not join.IntoKeyword.IsMissing AndAlso join.IntoKeyword.SpanStart <= position Then
' Should return binder to lookup aggregate functions.
Dim binders As ImmutableArray(Of Binder) = GetQueryClauseLambdaBinders(join)
Dim binders As ImmutableArray(Of binder) = GetQueryClauseLambdaBinders(join)
#If DEBUG Then
Debug.Assert(Not binders.IsDefault OrElse Not ShouldHaveFound(join, guard:=True))
Debug.Assert(binders.IsDefault OrElse binders.Length = 3)
......@@ -1386,7 +1386,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Function
Private Function GetJoinClauseLambdaBinder(join As JoinClauseSyntax, position As Integer) As Binder
Dim binder As Binder = Nothing
Dim binder As binder = Nothing
' If position were in context of an additional join that join would have handled it, unless there were
' no need for a special binder.
......@@ -1394,7 +1394,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
' If position is in context of an 'On' clause, there is a binder that we need to return.
If Not join.OnKeyword.IsMissing AndAlso join.OnKeyword.SpanStart <= position AndAlso SyntaxFacts.InSpanOrEffectiveTrailingOfNode(join, position) Then
Dim binders As ImmutableArray(Of Binder) = GetQueryClauseLambdaBinders(join)
Dim binders As ImmutableArray(Of binder) = GetQueryClauseLambdaBinders(join)
#If DEBUG Then
Debug.Assert(Not binders.IsDefault OrElse Not ShouldHaveFound(join, guard:=True))
Debug.Assert(binders.IsDefault OrElse (binders.Length > 1 AndAlso binders.Length < 4 AndAlso binders(0) IsNot Nothing))
......@@ -1410,7 +1410,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Function
Private Function GetFromClauseLambdaBinder(from As FromClauseSyntax, position As Integer) As Binder
Dim binder As Binder = Nothing
Dim binder As binder = Nothing
If SyntaxFacts.InSpanOrEffectiveTrailingOfNode(from, position) Then
binder = GetCollectionRangeVariablesLambdaBinder(from.Variables, position)
......@@ -1420,7 +1420,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Function
Private Function GetCollectionRangeVariablesLambdaBinder(variables As SeparatedSyntaxList(Of CollectionRangeVariableSyntax), position As Integer) As Binder
Dim binder As Binder = Nothing
Dim binder As binder = Nothing
For i As Integer = 0 To variables.Count - 1
Dim item As CollectionRangeVariableSyntax = variables(i)
......@@ -1435,7 +1435,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Not (item.Parent.Parent.Kind = SyntaxKind.QueryExpression AndAlso
DirectCast(item.Parent.Parent, QueryExpressionSyntax).Clauses.FirstOrDefault Is item.Parent)) Then
Dim binders As ImmutableArray(Of Binder) = GetQueryClauseLambdaBinders(item)
Dim binders As ImmutableArray(Of binder) = GetQueryClauseLambdaBinders(item)
#If DEBUG Then
Debug.Assert(Not binders.IsDefault OrElse Not ShouldHaveFound(item, guard:=True))
Debug.Assert(binders.IsDefault OrElse (binders.Length > 0 AndAlso binders.Length < 3 AndAlso binders(0) IsNot Nothing))
......@@ -1456,13 +1456,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Private Function GetLetClauseLambdaBinder([let] As LetClauseSyntax, position As Integer) As Binder
Dim binder As Binder = Nothing
Dim binder As binder = Nothing
If SyntaxFacts.InSpanOrEffectiveTrailingOfNode([let], position) Then
For Each item As ExpressionRangeVariableSyntax In [let].Variables
If SyntaxFacts.InSpanOrEffectiveTrailingOfNode(item, position) OrElse position < item.SpanStart Then
Dim binders As ImmutableArray(Of Binder) = GetQueryClauseLambdaBinders(item)
Dim binders As ImmutableArray(Of binder) = GetQueryClauseLambdaBinders(item)
#If DEBUG Then
Debug.Assert(Not binders.IsDefault OrElse Not ShouldHaveFound([let], guard:=True))
Debug.Assert(binders.IsDefault OrElse (binders.Length = 1 AndAlso binders(0) IsNot Nothing))
......@@ -1482,10 +1482,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Function
Private Function GetGroupByClauseLambdaBinder(groupBy As GroupByClauseSyntax, position As Integer) As Binder
Dim binder As Binder = Nothing
Dim binder As binder = Nothing
If SyntaxFacts.InSpanOrEffectiveTrailingOfNode(groupBy, position) Then
Dim binders As ImmutableArray(Of Binder) = GetQueryClauseLambdaBinders(groupBy)
Dim binders As ImmutableArray(Of binder) = GetQueryClauseLambdaBinders(groupBy)
#If DEBUG Then
Debug.Assert(Not binders.IsDefault OrElse Not ShouldHaveFound(groupBy, guard:=True))
Debug.Assert(binders.IsDefault OrElse (binders.Length = 2 OrElse binders.Length = 3))
......@@ -1518,12 +1518,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Function
Private Function GetFunctionAggregationLambdaBinder(func As FunctionAggregationSyntax, position As Integer) As Binder
Dim binder As Binder = Nothing
Dim binder As binder = Nothing
If Not func.OpenParenToken.IsMissing AndAlso func.OpenParenToken.SpanStart <= position AndAlso
((func.CloseParenToken.IsMissing AndAlso SyntaxFacts.InSpanOrEffectiveTrailingOfNode(func, position)) OrElse position < func.CloseParenToken.SpanStart) Then
Dim binders As ImmutableArray(Of Binder) = GetQueryClauseLambdaBinders(func)
Dim binders As ImmutableArray(Of binder) = GetQueryClauseLambdaBinders(func)
#If DEBUG Then
Debug.Assert(Not binders.IsDefault OrElse Not ShouldHaveFound(func, guard:=True))
Debug.Assert(binders.IsDefault OrElse (binders.Length = 1 AndAlso binders(0) IsNot Nothing))
......@@ -1613,7 +1613,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
If SyntaxFacts.InSpanOrEffectiveTrailingOfNode(initialization, position) Then
Dim cachedBinder As Binder.AnonymousTypeFieldInitializerBinder = Nothing
Dim cachedBinder As binder.AnonymousTypeFieldInitializerBinder = Nothing
rwLock.EnterReadLock()
Try
......@@ -1627,7 +1627,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
' Get bound node for the whole AnonymousType initializer expression.
' This will build required maps for it.
Dim boundNode As BoundNode = GetUpperBoundNode(initialization.Parent.Parent)
Dim boundNode As boundNode = GetUpperBoundNode(initialization.Parent.Parent)
rwLock.EnterReadLock()
Try
......@@ -1665,7 +1665,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Function
Private Function GetLambdaBodyBinder(lambda As LambdaExpressionSyntax) As LambdaBodyBinder
Dim boundLambda As BoundLambda = GetBoundLambda(lambda)
Dim boundLambda As boundLambda = GetBoundLambda(lambda)
If boundLambda IsNot Nothing Then
Return boundLambda.LambdaBinderOpt
......@@ -1934,7 +1934,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
''' in effect on nested binders.
''' </summary>
Public Overrides Function GetBinder(node As VisualBasicSyntaxNode) As Binder
Dim binder As Binder = Me.ContainingBinder.GetBinder(node)
Dim binder As binder = Me.ContainingBinder.GetBinder(node)
If binder IsNot Nothing Then
Debug.Assert(Not (TypeOf binder Is IncrementalBinder))
......@@ -1949,7 +1949,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
''' in effect on nested binders.
''' </summary>
Public Overrides Function GetBinder(list As SyntaxList(Of StatementSyntax)) As Binder
Dim binder As Binder = Me.ContainingBinder.GetBinder(list)
Dim binder As binder = Me.ContainingBinder.GetBinder(list)
If binder IsNot Nothing Then
Debug.Assert(Not (TypeOf binder Is IncrementalBinder))
......
......@@ -9,15 +9,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Friend NotInheritable Class MethodBodySemanticModel
Inherits MemberSemanticModel
Private Sub New(root As VisualBasicSyntaxNode, binder As Binder, Optional parentSemanticModelOpt As SyntaxTreeSemanticModel = Nothing, Optional speculatedPosition As Integer = 0, Optional isSuppressingAccessChecks As Boolean = False)
MyBase.New(root, binder, parentSemanticModelOpt, speculatedPosition, isSuppressingAccessChecks:=isSuppressingAccessChecks)
Private Sub New(root As VisualBasicSyntaxNode, binder As Binder, Optional parentSemanticModelOpt As SyntaxTreeSemanticModel = Nothing, Optional speculatedPosition As Integer = 0, Optional ignoreAccessibility As Boolean = False)
MyBase.New(root, binder, parentSemanticModelOpt, speculatedPosition, ignoreAccessibility:=ignoreAccessibility)
End Sub
''' <summary>
''' Creates an MethodBodySemanticModel that allows asking semantic questions about an attribute node.
''' </summary>
Friend Shared Function Create(binder As MethodBodyBinder, Optional isSuppressingAccessChecks As Boolean = False) As MethodBodySemanticModel
Return New MethodBodySemanticModel(binder.Root, binder, isSuppressingAccessChecks:=isSuppressingAccessChecks)
Friend Shared Function Create(binder As MethodBodyBinder, Optional ignoreAccessibility As Boolean = False) As MethodBodySemanticModel
Return New MethodBodySemanticModel(binder.Root, binder, ignoreAccessibility:=ignoreAccessibility)
End Function
''' <summary>
......@@ -36,15 +36,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
' CONSIDER: Do we want to ensure that speculated method and the original method have identical signatures?
' Create a speculative binder for the method body.
Dim methodSymbol = DirectCast(Me.MemberSymbol, MethodSymbol)
Dim methodSymbol = DirectCast(Me.MemberSymbol, methodSymbol)
Dim containingBinder As Binder = Me.RootBinder
Dim containingBinder As binder = Me.RootBinder
' Get up to the NamedTypeBinder
Dim namedTypeBinder As NamedTypeBinder
Dim namedTypeBinder As namedTypeBinder
Do
namedTypeBinder = TryCast(containingBinder, NamedTypeBinder)
namedTypeBinder = TryCast(containingBinder, namedTypeBinder)
If namedTypeBinder IsNot Nothing Then
Exit Do
......@@ -53,7 +53,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
containingBinder = containingBinder.ContainingBinder
Loop
Dim methodBodyBinder = BinderBuilder.CreateBinderForMethodBody(methodSymbol, method, SemanticModelBinder.Mark(namedTypeBinder, HasAccessChecksSuppressed))
Dim methodBodyBinder = BinderBuilder.CreateBinderForMethodBody(methodSymbol, method, SemanticModelBinder.Mark(namedTypeBinder, IgnoresAccessibility))
' Wrap this binder with a BlockBaseBinder to hold onto the locals declared within the statement.
Dim binder = New StatementListBinder(methodBodyBinder, method.Statements)
......@@ -91,8 +91,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Friend NotInheritable Class TopLevelCodeSemanticModel
Inherits MemberSemanticModel
Public Sub New(binder As TopLevelCodeBinder, Optional isSuppressingAccessChecks As Boolean = False)
MyBase.New(binder.Root, binder, parentSemanticModelOpt:=Nothing, speculatedPosition:=0, isSuppressingAccessChecks:=isSuppressingAccessChecks)
Public Sub New(binder As TopLevelCodeBinder, Optional ignoreAccessibility As Boolean = False)
MyBase.New(binder.Root, binder, parentSemanticModelOpt:=Nothing, speculatedPosition:=0, ignoreAccessibility:=ignoreAccessibility)
End Sub
Friend Overrides Function TryGetSpeculativeSemanticModelForMethodBodyCore(parentModel As SyntaxTreeSemanticModel, position As Integer, method As MethodBlockBaseSyntax, <Out> ByRef speculativeModel As SemanticModel) As Boolean
......
......@@ -25,16 +25,16 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Private ReadOnly _sourceModule As SourceModuleSymbol
Private ReadOnly _syntaxTree As SyntaxTree
Private ReadOnly _binderFactory As BinderFactory
Private ReadOnly _hasAccessChecksSuppressed As Boolean
Private ReadOnly _ignoresAccessibility As Boolean
' maps from a higher-level binder to an appropriate SemanticModel for the construct (such as a method, or initializer).
Private ReadOnly _semanticModelCache As New ConcurrentDictionary(Of Tuple(Of Binder, Boolean), MemberSemanticModel)()
Friend Sub New(compilation As VisualBasicCompilation, sourceModule As SourceModuleSymbol, syntaxTree As SyntaxTree, Optional suppressAccessChecks As Boolean = False)
Friend Sub New(compilation As VisualBasicCompilation, sourceModule As SourceModuleSymbol, syntaxTree As SyntaxTree, Optional ignoreAccessibility As Boolean = False)
_compilation = compilation
_sourceModule = sourceModule
_syntaxTree = syntaxTree
_hasAccessChecksSuppressed = suppressAccessChecks
_ignoresAccessibility = ignoreAccessibility
_binderFactory = New BinderFactory(sourceModule, syntaxTree)
End Sub
......@@ -68,9 +68,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
''' <summary>
''' Returns true if this Is a SemanticModel that ignores accessibility rules when answering semantic questions.
''' </summary>
Public NotOverridable Overrides ReadOnly Property HasAccessChecksSuppressed As Boolean
Public NotOverridable Overrides ReadOnly Property IgnoresAccessibility As Boolean
Get
Return Me._hasAccessChecksSuppressed
Return Me._ignoresAccessibility
End Get
End Property
......@@ -151,19 +151,19 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Public Function GetMemberSemanticModel(binder As Binder) As MemberSemanticModel
If TypeOf binder Is MethodBodyBinder Then
Return _semanticModelCache.GetOrAdd(Tuple.Create(binder, HasAccessChecksSuppressed), _methodBodySemanticModelCreator)
Return _semanticModelCache.GetOrAdd(Tuple.Create(binder, IgnoresAccessibility), _methodBodySemanticModelCreator)
End If
If TypeOf binder Is DeclarationInitializerBinder Then
Return _semanticModelCache.GetOrAdd(Tuple.Create(binder, HasAccessChecksSuppressed), _initializerSemanticModelCreator)
Return _semanticModelCache.GetOrAdd(Tuple.Create(binder, IgnoresAccessibility), _initializerSemanticModelCreator)
End If
If TypeOf binder Is AttributeBinder Then
Return _semanticModelCache.GetOrAdd(Tuple.Create(binder, HasAccessChecksSuppressed), _attributeSemanticModelCreator)
Return _semanticModelCache.GetOrAdd(Tuple.Create(binder, IgnoresAccessibility), _attributeSemanticModelCreator)
End If
If TypeOf binder Is TopLevelCodeBinder Then
Return _semanticModelCache.GetOrAdd(Tuple.Create(binder, HasAccessChecksSuppressed), _topLevelCodeSemanticModelCreator)
Return _semanticModelCache.GetOrAdd(Tuple.Create(binder, IgnoresAccessibility), _topLevelCodeSemanticModelCreator)
End If
Return Nothing
......@@ -189,7 +189,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return model.GetEnclosingBinder(position)
Else
Dim binder As binder = _binderFactory.GetBinderForPosition(FindInitialNodeFromPosition(position), position)
Return SemanticModelBinder.Mark(binder, HasAccessChecksSuppressed)
Return SemanticModelBinder.Mark(binder, IgnoresAccessibility)
End If
End Function
......@@ -583,7 +583,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End If
Dim docCommentBinder = Me._binderFactory.GetBinderForPosition(node, node.SpanStart)
docCommentBinder = SemanticModelBinder.Mark(docCommentBinder, HasAccessChecksSuppressed)
docCommentBinder = SemanticModelBinder.Mark(docCommentBinder, IgnoresAccessibility)
If isCrefAttribute Then
Dim symbols As ImmutableArray(Of Symbol)
......
......@@ -1829,8 +1829,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
''' which has a cache. Therefore, one effectively clears the cache by discarding the
''' SemanticModel.
'''</summary>
Public Shadows Function GetSemanticModel(syntaxTree As SyntaxTree, Optional suppressAccessChecks As Boolean = False) As SemanticModel
Return New SyntaxTreeSemanticModel(Me, DirectCast(Me.SourceModule, SourceModuleSymbol), syntaxTree, suppressAccessChecks)
Public Shadows Function GetSemanticModel(syntaxTree As SyntaxTree, Optional ignoreAccessibility As Boolean = False) As SemanticModel
Return New SyntaxTreeSemanticModel(Me, DirectCast(Me.SourceModule, SourceModuleSymbol), syntaxTree, ignoreAccessibility)
End Function
#End Region
......@@ -2504,8 +2504,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Get
End Property
Protected Overrides Function CommonGetSemanticModel(syntaxTree As SyntaxTree, suppressAccessChecks As Boolean) As SemanticModel
Return Me.GetSemanticModel(syntaxTree, suppressAccessChecks)
Protected Overrides Function CommonGetSemanticModel(syntaxTree As SyntaxTree, ignoreAccessibility As Boolean) As SemanticModel
Return Me.GetSemanticModel(syntaxTree, ignoreAccessibility)
End Function
Protected Overrides ReadOnly Property CommonSyntaxTrees As IEnumerable(Of SyntaxTree)
......
......@@ -3048,7 +3048,7 @@ Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilation.AddSyntaxTrees(trees A
Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilation.ClassifyConversion(source As Microsoft.CodeAnalysis.ITypeSymbol, destination As Microsoft.CodeAnalysis.ITypeSymbol)
Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilation.Clone()
Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilation.ContainsSyntaxTree(syntaxTree As Microsoft.CodeAnalysis.SyntaxTree)
Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilation.GetSemanticModel(syntaxTree As Microsoft.CodeAnalysis.SyntaxTree, suppressAccessChecks As Boolean = False)
Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilation.GetSemanticModel(syntaxTree As Microsoft.CodeAnalysis.SyntaxTree, ignoreAccessibility As Boolean = False)
Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilation.LanguageVersion()
Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilation.Options()
Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilation.RemoveAllReferences()
......@@ -4360,7 +4360,7 @@ Overrides Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilation.CommonGetAss
Overrides Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilation.CommonGetCompilationNamespace(namespaceSymbol As Microsoft.CodeAnalysis.INamespaceSymbol)
Overrides Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilation.CommonGetEntryPoint(cancellationToken As System.Threading.CancellationToken)
Overrides Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilation.CommonGetMetadataReference(_assemblySymbol As Microsoft.CodeAnalysis.IAssemblySymbol)
Overrides Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilation.CommonGetSemanticModel(syntaxTree As Microsoft.CodeAnalysis.SyntaxTree, suppressAccessChecks As Boolean)
Overrides Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilation.CommonGetSemanticModel(syntaxTree As Microsoft.CodeAnalysis.SyntaxTree, ignoreAccessibility As Boolean)
Overrides Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilation.CommonGetSpecialType(specialType As Microsoft.CodeAnalysis.SpecialType)
Overrides Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilation.CommonGetSubmissionResultType(ByRef hasValue As Boolean)
Overrides Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilation.CommonGetTypeByMetadataName(metadataName As String)
......
......@@ -520,18 +520,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax
Partial Class KeywordSyntax
Private Shared ReadOnly BoxedTrue As Object = True
Private Shared ReadOnly BoxedFalse As Object = False
Friend NotOverridable Overrides ReadOnly Property ObjectValue As Object
Get
Select Case MyBase.Kind
Case SyntaxKind.NothingKeyword
Return Nothing
Case SyntaxKind.TrueKeyword
Return BoxedTrue
Return Boxes.BoxedTrue
Case SyntaxKind.FalseKeyword
Return BoxedFalse
Return Boxes.BoxedFalse
Case Else
Return Me.Text
End Select
......@@ -545,4 +542,3 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax
End Property
End Class
End Namespace
Imports Microsoft.CodeAnalysis
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.Test.Utilities
Imports Microsoft.CodeAnalysis.VisualBasic
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
......@@ -10,7 +12,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests
Public Class SuppressAccessibilityChecksTests
Inherits BasicTestBase
Private Function GetSemanticModelWithSuppressAccessChecks() As SemanticModel
Private Function GetSemanticModelWithIgnoreAccessibility() As SemanticModel
Dim compilationA = CreateVisualBasicCompilation(<![CDATA[
......@@ -43,12 +45,12 @@ End Class
compilationOptions:=TestOptions.ReleaseDll.WithMetadataImportOptions(MetadataImportOptions.All))
Dim syntaxTree2 = compilationB.SyntaxTrees(0)
Return compilationB.GetSemanticModel(syntaxTree2, suppressAccessChecks:=True)
Return compilationB.GetSemanticModel(syntaxTree2, ignoreAccessibility:=True)
End Function
<Fact>
Public Sub TestAccessPrivateMemberOfInternalType()
Dim semanticModel = GetSemanticModelWithSuppressAccessChecks()
Dim semanticModel = GetSemanticModelWithIgnoreAccessibility()
Dim invocation = semanticModel.SyntaxTree.GetRoot().DescendantNodes().OfType(Of InvocationExpressionSyntax)().Single()
Dim position = invocation.FullSpan.Start
......@@ -61,7 +63,7 @@ End Class
<Fact>
Public Sub TestAccessChecksInSpeculativeExpression()
Dim semanticModel = GetSemanticModelWithSuppressAccessChecks()
Dim semanticModel = GetSemanticModelWithIgnoreAccessibility()
Dim invocation = semanticModel.SyntaxTree.GetRoot().DescendantNodes().OfType(Of InvocationExpressionSyntax)().Single()
Dim speculativeInvocation = SyntaxFactory.ParseExpression("New A().M()._num")
......@@ -73,7 +75,7 @@ End Class
<Fact>
Public Sub TestAccessChecksInSpeculativeSemanticModel()
Dim semanticModel = GetSemanticModelWithSuppressAccessChecks()
Dim semanticModel = GetSemanticModelWithIgnoreAccessibility()
Dim syntaxTree = semanticModel.SyntaxTree
Dim invocation = syntaxTree.GetRoot().DescendantNodes().OfType(Of InvocationExpressionSyntax)().Single()
Dim position = invocation.FullSpan.Start
......@@ -110,7 +112,7 @@ End Class
Dim tree = SyntaxFactory.ParseSyntaxTree(source)
Dim comp = CreateCompilationWithMscorlib(tree)
Dim model = comp.GetSemanticModel(tree, suppressAccessChecks:=True)
Dim model = comp.GetSemanticModel(tree, ignoreAccessibility:=True)
Dim root = tree.GetCompilationUnitRoot()
Dim expr = DirectCast(root.DescendantNodes().OfType(Of SingleLineLambdaExpressionSyntax)().Single().Body, ExpressionSyntax)
......@@ -180,7 +182,7 @@ End Class
]]>.Value}, New MetadataReference() {referenceA}, TestOptions.ReleaseDll.WithMetadataImportOptions(MetadataImportOptions.All))
Dim syntaxTree = compilationB.SyntaxTrees(0)
Dim semanticModel = compilationB.GetSemanticModel(syntaxTree, suppressAccessChecks:=True)
Dim semanticModel = compilationB.GetSemanticModel(syntaxTree, ignoreAccessibility:=True)
Dim invocation = syntaxTree.GetRoot().DescendantNodes().OfType(Of InvocationExpressionSyntax)().Single()
......@@ -237,7 +239,7 @@ End Class
Dim typeDecl = DirectCast(root.Members(1), ClassBlockSyntax)
Dim propertyDecl = DirectCast(typeDecl.Members(0), PropertyBlockSyntax)
Dim methodDecl = propertyDecl.Accessors(0)
Dim model = compilationA.GetSemanticModel(tree, suppressAccessChecks:=True)
Dim model = compilationA.GetSemanticModel(tree, ignoreAccessibility:=True)
Dim speculatedMethod =
propertyDecl.ReplaceNode(propertyDecl.Accessors(0), blockStatement.ChildNodes().OfType(Of PropertyBlockSyntax).Single().Accessors(0))
......
......@@ -29,7 +29,7 @@
/r:System.Web.Mobile.dll
/r:System.Web.RegularExpressions.dll
/r:System.Web.Services.dll
/r:System.Windows.Forms.Dll
/r:System.Windows.Forms.dll
/r:System.XML.dll
/r:System.Workflow.Activities.dll
......
......@@ -100,7 +100,7 @@ public void AppendIntersectingSpans(int start, int length, IntervalIntrospector
return;
}
var result = _lastDiagnostics.GetIntersectingInOrderIntervals(start, length, introspector, skipZeroLengthIntervals: false);
var result = _lastDiagnostics.GetIntersectingInOrderIntervals(start, length, introspector);
if (result.Count == 0)
{
return;
......
......@@ -127,5 +127,45 @@ public void TestTagSpanOrdering()
lastStart = tag.Span.Start.Position;
}
}
[Fact]
public void TestEmptySpanIntersects1()
{
var tree = CreateTree("foo", new Span(0, 0));
var spans = tree.GetIntersectingSpans(new SnapshotSpan(tree.Buffer.CurrentSnapshot, new Span(0, 0)));
Assert.True(spans.Count == 1);
}
[Fact]
public void TestEmptySpanIntersects2()
{
var tree = CreateTree("foo", new Span(0, 0));
var spans = tree.GetIntersectingSpans(new SnapshotSpan(tree.Buffer.CurrentSnapshot, new Span(0, "foo".Length)));
Assert.True(spans.Count == 1);
}
[Fact]
public void TestEmptySpanIntersects3()
{
var tree = CreateTree("foo", new Span(1, 0));
var spans = tree.GetIntersectingSpans(new SnapshotSpan(tree.Buffer.CurrentSnapshot, new Span(0, 1)));
Assert.True(spans.Count == 1);
}
[Fact]
public void TestEmptySpanIntersects4()
{
var tree = CreateTree("foo", new Span(1, 0));
var spans = tree.GetIntersectingSpans(new SnapshotSpan(tree.Buffer.CurrentSnapshot, new Span(1, 0)));
Assert.True(spans.Count == 1);
}
[Fact]
public void TestEmptySpanIntersects5()
{
var tree = CreateTree("foo", new Span(1, 0));
var spans = tree.GetIntersectingSpans(new SnapshotSpan(tree.Buffer.CurrentSnapshot, new Span(1, 1)));
Assert.True(spans.Count == 1);
}
}
}
......@@ -26,7 +26,7 @@ private class SnapshotSourceText : SourceText
/// <summary>
/// Use a separate class for closed files to simplify memory leak investigations
/// </summary>
internal class ClosedSnapshotSourceText : SnapshotSourceText
internal sealed class ClosedSnapshotSourceText : SnapshotSourceText
{
public ClosedSnapshotSourceText(ITextSnapshot roslynSnapshot, Encoding encodingOpt)
: base(roslynSnapshot, encodingOpt, containerOpt: null)
......@@ -43,7 +43,6 @@ public ClosedSnapshotSourceText(ITextSnapshot roslynSnapshot, Encoding encodingO
private readonly Encoding _encodingOpt;
private readonly TextBufferContainer _containerOpt;
private readonly int _reiteratedVersion;
private LineInfo _lineInfo;
private SnapshotSourceText(ITextSnapshot editorSnapshot, Encoding encodingOpt)
{
......@@ -145,17 +144,9 @@ public override int Length
}
#region Lines
public override TextLineCollection Lines
protected override TextLineCollection GetLinesCore()
{
get
{
if (_lineInfo == null)
{
System.Threading.Interlocked.CompareExchange(ref _lineInfo, new LineInfo(this), null);
}
return _lineInfo;
}
return new LineInfo(this);
}
private class LineInfo : TextLineCollection
......
......@@ -585,7 +585,7 @@ private static BoundStatement BindAssignment(Binder binder, ExpressionSyntax syn
var binder = (new BuckStopsHereBinder(compilation)).WithAdditionalFlags(
BinderFlags.SuppressObsoleteChecks |
BinderFlags.SuppressAccessChecks |
BinderFlags.IgnoreAccessibility |
BinderFlags.UnsafeRegion |
BinderFlags.UncheckedRegion |
BinderFlags.AllowManagedAddressOf |
......
......@@ -287,6 +287,16 @@ private async Task<ProjectAnalyzersAndStates> GetOrCreateProjectAnalyzersAndStat
var workspaceAnalyzersCount = _sharedAnalyzersAndStates.GetAnalyzerCount(project.Language);
newProjectAnalyzersAndStates = ProjectAnalyzersAndStates.CreateIfAnyAnalyzers(newAnalyzers, workspaceAnalyzersCount, project.Language);
// this cache logic is completely broken. cache can't be used in this way. if we didn't have an issue before that is just purely by luck.
// the reason it is broken is that, this method can be called from any place (no central call path so, can't figure out all the possible paths, but I confirmed that there
// are at least more than one path) from any workspace snapshot from any thread but the cache doesn't have any versioning or snapshot check,
// but regardless, this code updates the cache. which introduce a race where if code uses the cache in 2 different places in the same method, the return value might be different.
// and that is causing us to crash since one gets two completely different state.
//
// I tried to figure out how to fix this but, eventually gave up since it is so deeply spread in the code, I don't see any way to properly fix this.
// my conculusion is ripping out this code and re-write this state management code.
return _projectAnalyzersAndStatesMap.AddOrUpdate(project.Id, newProjectAnalyzersAndStates, (k, c) => newProjectAnalyzersAndStates);
}
}
......
......@@ -104,6 +104,8 @@ protected void OnDataRemoved(object key)
_map.Remove(key);
}
factory.OnUpdated();
// let table manager know that we want to clear the entries
for (var i = 0; i < snapshot.Length; i++)
{
......
......@@ -30,7 +30,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.ProjectSystemShim
Function CompileAndGetErrorCount(metadataService As IMetadataService) As Integer
Dim trees = _files.Select(Function(path)
Using stream = FileUtilities.OpenRead(path)
Return SyntaxFactory.ParseSyntaxTree(EncodedStringText.From(stream), options:=_compilerOptions.ParseOptions, path:=path)
Return SyntaxFactory.ParseSyntaxTree(SourceText.From(stream), options:=_compilerOptions.ParseOptions, path:=path)
End Using
End Function)
......
// 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.Diagnostics;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.Formatting
......@@ -291,7 +287,8 @@ private bool ShouldFormat()
OnComment(trivia, index) ||
OnSkippedTokensOrText(trivia) ||
OnRegion(trivia, index) ||
OnPreprocessor(trivia, index))
OnPreprocessor(trivia, index) ||
OnDisabledTextTrivia(trivia, index))
{
return true;
}
......@@ -300,6 +297,20 @@ private bool ShouldFormat()
return false;
}
private bool OnDisabledTextTrivia(SyntaxTrivia trivia, int index)
{
if (trivia.IsKind(SyntaxKind.DisabledTextTrivia))
{
var triviaString = trivia.ToString();
if (!string.IsNullOrEmpty(triviaString) && SyntaxFacts.IsNewLine(triviaString.Last()))
{
ResetStateAfterNewLine(index);
}
}
return false;
}
private static bool ShouldFormatSingleLineDocumentationComment(int indentation, int tabSize, SyntaxTrivia trivia)
{
var xmlComment = (DocumentationCommentTriviaSyntax)trivia.GetStructure();
......
......@@ -5910,6 +5910,101 @@ void M()
}
}
}";
AssertFormat(expected, code);
}
[WorkItem(285)]
[WorkItem(1089196)]
[Fact, Trait(Traits.Feature, Traits.Features.Formatting)]
public void FormatHashInBadDirectiveToZeroColumnAnywhereInsideIfDef()
{
const string code = @"class MyClass
{
static void Main(string[] args)
{
#if false
#
#endif
}
}";
const string expected = @"class MyClass
{
static void Main(string[] args)
{
#if false
#
#endif
}
}";
AssertFormat(expected, code);
}
[WorkItem(285)]
[WorkItem(1089196)]
[Fact, Trait(Traits.Feature, Traits.Features.Formatting)]
public void FormatHashElseToZeroColumnAnywhereInsideIfDef()
{
const string code = @"class MyClass
{
static void Main(string[] args)
{
#if false
#else
Appropriate indentation should be here though #
#endif
}
}";
const string expected = @"class MyClass
{
static void Main(string[] args)
{
#if false
#else
Appropriate indentation should be here though #
#endif
}
}";
AssertFormat(expected, code);
}
[WorkItem(285)]
[WorkItem(1089196)]
[Fact, Trait(Traits.Feature, Traits.Features.Formatting)]
public void FormatHashsToZeroColumnAnywhereInsideIfDef()
{
const string code = @"class MyClass
{
static void Main(string[] args)
{
#if false
#else
#
#endif
}
}";
const string expected = @"class MyClass
{
static void Main(string[] args)
{
#if false
#else
#
#endif
}
}";
AssertFormat(expected, code);
}
......
......@@ -61,9 +61,6 @@
<Compile Include="..\..\..\Compilers\Core\Desktop\AssemblyReferenceResolver.cs">
<Link>InternalUtilities\AssemblyReferenceResolver.cs</Link>
</Compile>
<Compile Include="..\..\..\Compilers\Core\Desktop\LargeEncodedText.cs">
<Link>InternalUtilities\LargeEncodedText.cs</Link>
</Compile>
<Compile Include="..\..\..\Compilers\Core\Desktop\MetadataFileReferenceResolver.cs">
<Link>InternalUtilities\MetadataFileReferenceResolver.cs</Link>
</Compile>
......
......@@ -153,7 +153,7 @@ public void InsertAfter(SyntaxNode node, IEnumerable<SyntaxNode> newNodes)
public void InsertAfter(SyntaxNode node, SyntaxNode newNode)
{
CheckNodeInTree(node);
this.InsertBefore(node, new[] { newNode });
this.InsertAfter(node, new[] { newNode });
}
private void CheckNodeInTree(SyntaxNode node)
......
......@@ -26,7 +26,7 @@ public ContextIntervalTree(IIntervalIntrospector<T> introspector)
{
_edgeExclusivePredicate = ContainsEdgeExclusive;
_edgeInclusivePredicate = ContainsEdgeInclusive;
_containPredicate = (value, start, end) => Contains(value, start, end, Introspector, skipZeroLengthIntervals: true);
_containPredicate = (value, start, end) => Contains(value, start, end, Introspector);
}
public void AddIntervalInPlace(T value)
......
......@@ -18,7 +18,7 @@ internal partial class IntervalTree<T> : IEnumerable<T>
protected Node root;
private delegate bool TestInterval(T value, int start, int length, IIntervalIntrospector<T> introspector, bool skipZeroLengthIntervals);
private delegate bool TestInterval(T value, int start, int length, IIntervalIntrospector<T> introspector);
private static readonly TestInterval s_intersectsWithTest = IntersectsWith;
private static readonly TestInterval s_containsTest = Contains;
private static readonly TestInterval s_overlapsWithTest = OverlapsWith;
......@@ -42,7 +42,7 @@ public IntervalTree(IIntervalIntrospector<T> introspector, IEnumerable<T> values
}
}
protected static bool Contains(T value, int start, int length, IIntervalIntrospector<T> introspector, bool skipZeroLengthIntervals)
protected static bool Contains(T value, int start, int length, IIntervalIntrospector<T> introspector)
{
var otherStart = start;
var otherEnd = start + length;
......@@ -50,12 +50,6 @@ protected static bool Contains(T value, int start, int length, IIntervalIntrospe
var thisEnd = GetEnd(value, introspector);
var thisStart = introspector.GetStart(value);
if (thisStart == thisEnd &&
skipZeroLengthIntervals)
{
return false;
}
// make sure "Contains" test to be same as what TextSpan does
if (length == 0)
{
......@@ -65,7 +59,7 @@ protected static bool Contains(T value, int start, int length, IIntervalIntrospe
return thisStart <= otherStart && otherEnd <= thisEnd;
}
private static bool IntersectsWith(T value, int start, int length, IIntervalIntrospector<T> introspector, bool skipZeroLengthIntervals)
private static bool IntersectsWith(T value, int start, int length, IIntervalIntrospector<T> introspector)
{
var otherStart = start;
var otherEnd = start + length;
......@@ -73,16 +67,10 @@ private static bool IntersectsWith(T value, int start, int length, IIntervalIntr
var thisEnd = GetEnd(value, introspector);
var thisStart = introspector.GetStart(value);
if (thisStart == thisEnd &&
skipZeroLengthIntervals)
{
return false;
}
return otherStart <= thisEnd && otherEnd >= thisStart;
}
private static bool OverlapsWith(T value, int start, int length, IIntervalIntrospector<T> introspector, bool skipZeroLengthIntervals)
private static bool OverlapsWith(T value, int start, int length, IIntervalIntrospector<T> introspector)
{
var otherStart = start;
var otherEnd = start + length;
......@@ -90,12 +78,6 @@ private static bool OverlapsWith(T value, int start, int length, IIntervalIntros
var thisEnd = GetEnd(value, introspector);
var thisStart = introspector.GetStart(value);
if (thisStart == thisEnd &&
skipZeroLengthIntervals)
{
return false;
}
if (length == 0)
{
return thisStart < otherStart && otherStart < thisEnd;
......@@ -107,24 +89,24 @@ private static bool OverlapsWith(T value, int start, int length, IIntervalIntros
return overlapStart < overlapEnd;
}
public IEnumerable<T> GetOverlappingIntervals(int start, int length, IIntervalIntrospector<T> introspector, bool skipZeroLengthIntervals = true)
public IEnumerable<T> GetOverlappingIntervals(int start, int length, IIntervalIntrospector<T> introspector)
{
return this.GetPreOrderIntervals(start, length, s_overlapsWithTest, introspector, skipZeroLengthIntervals);
return this.GetPreOrderIntervals(start, length, s_overlapsWithTest, introspector);
}
public IEnumerable<T> GetIntersectingIntervals(int start, int length, IIntervalIntrospector<T> introspector, bool skipZeroLengthIntervals = true)
public IEnumerable<T> GetIntersectingIntervals(int start, int length, IIntervalIntrospector<T> introspector)
{
return this.GetPreOrderIntervals(start, length, s_intersectsWithTest, introspector, skipZeroLengthIntervals);
return this.GetPreOrderIntervals(start, length, s_intersectsWithTest, introspector);
}
public IList<T> GetIntersectingInOrderIntervals(int start, int length, IIntervalIntrospector<T> introspector, bool skipZeroLengthIntervals = true)
public IList<T> GetIntersectingInOrderIntervals(int start, int length, IIntervalIntrospector<T> introspector)
{
return this.GetInOrderIntervals(start, length, s_intersectsWithTest, introspector, skipZeroLengthIntervals);
return this.GetInOrderIntervals(start, length, s_intersectsWithTest, introspector);
}
public IEnumerable<T> GetContainingIntervals(int start, int length, IIntervalIntrospector<T> introspector, bool skipZeroLengthIntervals = true)
public IEnumerable<T> GetContainingIntervals(int start, int length, IIntervalIntrospector<T> introspector)
{
return this.GetPreOrderIntervals(start, length, s_containsTest, introspector, skipZeroLengthIntervals);
return this.GetPreOrderIntervals(start, length, s_containsTest, introspector);
}
public bool IntersectsWith(int position, IIntervalIntrospector<T> introspector)
......@@ -132,7 +114,7 @@ public bool IntersectsWith(int position, IIntervalIntrospector<T> introspector)
return GetIntersectingIntervals(position, 0, introspector).Any();
}
private IList<T> GetInOrderIntervals(int start, int length, TestInterval testInterval, IIntervalIntrospector<T> introspector, bool skipZeroLengthIntervals)
private IList<T> GetInOrderIntervals(int start, int length, TestInterval testInterval, IIntervalIntrospector<T> introspector)
{
List<T> result = null;
......@@ -167,7 +149,7 @@ private IList<T> GetInOrderIntervals(int start, int length, TestInterval testInt
}
currentNode = candidates.Pop();
if (testInterval(currentNode.Value, start, length, introspector, skipZeroLengthIntervals))
if (testInterval(currentNode.Value, start, length, introspector))
{
result = result ?? new List<T>();
result.Add(currentNode.Value);
......@@ -194,7 +176,7 @@ private IList<T> GetInOrderIntervals(int start, int length, TestInterval testInt
return result ?? SpecializedCollections.EmptyList<T>();
}
private IEnumerable<T> GetPreOrderIntervals(int start, int length, TestInterval testInterval, IIntervalIntrospector<T> introspector, bool skipZeroLengthIntervals)
private IEnumerable<T> GetPreOrderIntervals(int start, int length, TestInterval testInterval, IIntervalIntrospector<T> introspector)
{
if (root == null || GetEnd(root.MaxEndNode.Value, introspector) < start)
{
......@@ -229,7 +211,7 @@ private IEnumerable<T> GetPreOrderIntervals(int start, int length, TestInterval
candidates.Push(left);
}
if (testInterval(currentNode.Value, start, length, introspector, skipZeroLengthIntervals))
if (testInterval(currentNode.Value, start, length, introspector))
{
yield return currentNode.Value;
}
......
......@@ -19,7 +19,7 @@ protected SimpleIntervalTree(IIntervalIntrospector<T> introspector, Node root) :
{
if (introspector == null)
{
throw new ArgumentNullException("introspector");
throw new ArgumentNullException(nameof(introspector));
}
_introspector = introspector;
......
......@@ -48,6 +48,9 @@
</ProjectReference>
</ItemGroup>
<ItemGroup Label="Linked Files">
<Compile Include="..\..\..\Compilers\Core\Portable\Collections\Boxes.cs">
<Link>InternalUtilities\Boxes.cs</Link>
</Compile>
<Compile Include="..\..\..\Compilers\Core\Portable\Collections\ImmutableArrayExtensions.cs">
<Link>InternalUtilities\ImmutableArrayExtensions.cs</Link>
</Compile>
......@@ -925,4 +928,4 @@
<Import Project="..\..\..\..\build\VSL.Imports.Closed.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
</ImportGroup>
</Project>
</Project>
\ No newline at end of file
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis.CodeGeneration;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Editting
{
public class SyntaxEditorTests
{
private readonly Workspace EmptyWorkspace = new AdhocWorkspace();
private void VerifySyntax<TSyntax>(SyntaxNode node, string expectedText) where TSyntax : SyntaxNode
{
Assert.IsAssignableFrom(typeof(TSyntax), node);
var formatted = Formatter.Format(node, EmptyWorkspace);
var actualText = formatted.ToFullString();
Assert.Equal(expectedText, actualText);
}
private SyntaxEditor GetEditor(SyntaxNode root)
{
return new SyntaxEditor(root, this.EmptyWorkspace);
}
[Fact]
public void TestReplaceNode()
{
var code = @"
public class C
{
public int X;
}";
var cu = SyntaxFactory.ParseCompilationUnit(code);
var cls = cu.Members[0];
var editor = GetEditor(cu);
var fieldX = editor.Generator.GetMembers(cls)[0];
editor.ReplaceNode(fieldX, editor.Generator.FieldDeclaration("Y", editor.Generator.TypeExpression(SpecialType.System_String), Accessibility.Public));
var newRoot = editor.GetChangedRoot();
VerifySyntax<CompilationUnitSyntax>(
newRoot,
@"
public class C
{
public string Y;
}");
}
[Fact]
public void TestRemoveNode()
{
var code = @"
public class C
{
public int X;
}";
var cu = SyntaxFactory.ParseCompilationUnit(code);
var cls = cu.Members[0];
var editor = GetEditor(cu);
var fieldX = editor.Generator.GetMembers(cls)[0];
editor.RemoveNode(fieldX);
var newRoot = editor.GetChangedRoot();
VerifySyntax<CompilationUnitSyntax>(
newRoot,
@"
public class C
{
}");
}
[Fact]
public void TestInterAfter()
{
var code = @"
public class C
{
public int X;
}";
var cu = SyntaxFactory.ParseCompilationUnit(code);
var cls = cu.Members[0];
var editor = GetEditor(cu);
var fieldX = editor.Generator.GetMembers(cls)[0];
editor.InsertAfter(fieldX, editor.Generator.FieldDeclaration("Y", editor.Generator.TypeExpression(SpecialType.System_String), Accessibility.Public));
var newRoot = editor.GetChangedRoot();
VerifySyntax<CompilationUnitSyntax>(
newRoot,
@"
public class C
{
public int X;
public string Y;
}");
}
[Fact]
public void TestInterBefore()
{
var code = @"
public class C
{
public int X;
}";
var cu = SyntaxFactory.ParseCompilationUnit(code);
var cls = cu.Members[0];
var editor = GetEditor(cu);
var fieldX = editor.Generator.GetMembers(cls)[0];
editor.InsertBefore(fieldX, editor.Generator.FieldDeclaration("Y", editor.Generator.TypeExpression(SpecialType.System_String), Accessibility.Public));
var newRoot = editor.GetChangedRoot();
VerifySyntax<CompilationUnitSyntax>(
newRoot,
@"
public class C
{
public string Y;
public int X;
}");
}
[Fact]
public void TestTrackNode()
{
var code = @"
public class C
{
public int X;
}";
var cu = SyntaxFactory.ParseCompilationUnit(code);
var cls = cu.Members[0];
var editor = GetEditor(cu);
var fieldX = editor.Generator.GetMembers(cls)[0];
editor.TrackNode(fieldX);
var newRoot = editor.GetChangedRoot();
var currentFieldX = newRoot.GetCurrentNode(fieldX);
Assert.NotNull(currentFieldX);
}
[Fact]
public void TestMultipleEdits()
{
var code = @"
public class C
{
public int X;
}";
var cu = SyntaxFactory.ParseCompilationUnit(code);
var cls = cu.Members[0];
var editor = GetEditor(cu);
var fieldX = editor.Generator.GetMembers(cls)[0];
editor.InsertAfter(fieldX, editor.Generator.FieldDeclaration("Y", editor.Generator.TypeExpression(SpecialType.System_String), Accessibility.Public));
editor.InsertBefore(fieldX, editor.Generator.FieldDeclaration("Z", editor.Generator.TypeExpression(SpecialType.System_Object), Accessibility.Public));
editor.RemoveNode(fieldX);
var newRoot = editor.GetChangedRoot();
VerifySyntax<CompilationUnitSyntax>(
newRoot,
@"
public class C
{
public object Z;
public string Y;
}");
}
}
}
......@@ -96,6 +96,7 @@
<CodeAnalysisRuleSet>..\..\..\build\TestProjectRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Compile Include="Editting\SyntaxEditorTests.cs" />
<Compile Include="ExtensionOrdererTests.cs" />
<Compile Include="Host\WorkspaceServices\TestProjectCacheService.cs" />
<Compile Include="LinkedFileDiffMerging\LinkedFileDiffMergingTests.TextMerging.cs" />
......@@ -306,4 +307,4 @@
<Import Project="..\..\..\build\Roslyn.Toolsets.Xunit.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
</ImportGroup>
</Project>
</Project>
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册