Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions src/System.Xml.XDocument/System.Xml.XDocument.csproj
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />


<PropertyGroup>
<!-- Work around known Dev14 bug - see
https://connect.microsoft.com/VisualStudio/feedback/details/1000796/connect-file-uap-props-not-found-cant-build-a-portable-lib-on-vs14
-->
-->

<_WindowsKitBinPath>$(MSBuildProgramFiles32)\Windows Kits\8.1\bin\x86</_WindowsKitBinPath>
<_WindowsPhoneKitBinPath>$(MSBuildProgramFiles32)\Windows Phone Kits\8.1\bin</_WindowsPhoneKitBinPath>
<MakePriExeFullPath>$(_WindowsKitBinPath)\makepri.exe</MakePriExeFullPath>
Expand All @@ -16,8 +16,8 @@
<MakePriExtensionPath>$(_WindowsPhoneKitBinPath)\x86\MrmEnvironmentExtDl.dll</MakePriExtensionPath>
<MakePriExtensionPath_x64>$(_WindowsPhoneKitBinPath)\x64\MrmEnvironmentExtDl.dll</MakePriExtensionPath_x64>
</PropertyGroup>


<PropertyGroup>
<Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
<Platform Condition="'$(Platform)' == ''">AnyCPU</Platform>
Expand Down Expand Up @@ -61,6 +61,7 @@
<Reference Include="System.Runtime.Extensions" />
<!--System.Environment.get_CurrentManagedThreadId-->
<Reference Include="System.Threading" />
<Reference Include="System.Threading.Tasks" />
<!--For locking-->
<Reference Include="System.Reflection" />
<!--Need to reimplement Type.IsInstanceOfType-->
Expand Down
17 changes: 17 additions & 0 deletions src/System.Xml.XDocument/System/Xml/Linq/XComment.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Threading;
using System.Threading.Tasks;
namespace System.Xml.Linq
{
/// <summary>
Expand Down Expand Up @@ -92,6 +94,21 @@ public override void WriteTo(XmlWriter writer)
writer.WriteComment(value);
}

/// <summary>
/// Write this <see cref="XComment"/> to the passed in <see cref="XmlWriter"/>.
/// </summary>
/// <param name="writer">
/// The <see cref="XmlWriter"/> to write this <see cref="XComment"/> to.
/// </param>
/// <param name="cancellationToken">A cancellation token.</param>
public override async Task WriteToAsync(XmlWriter writer, CancellationToken cancellationToken)
{
if (writer == null) throw new ArgumentNullException("writer");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please put the throw statement on its own line to match the coding guidelines.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The single-line test/throw style in my patch is consistent with existing XLINQ code. Do you still prefer me to use the new guidelines within my patch, or should we hold off style changes for another PR?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes please ignore my comments on the one-line if statements as you are correct all this code still needs to be run through our formatting tool, we have issue https://github.com/dotnet/corefx/issues/496 tracking that.


cancellationToken.ThrowIfCancellationRequested();
await writer.WriteCommentAsync(value).ConfigureAwait(false);
}

internal override XNode CloneNode()
{
return new XComment(this);
Expand Down
250 changes: 178 additions & 72 deletions src/System.Xml.XDocument/System/Xml/Linq/XContainer.cs

Large diffs are not rendered by default.

232 changes: 229 additions & 3 deletions src/System.Xml.XDocument/System/Xml/Linq/XDocument.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.IO;
using System.Threading;
using System.Threading.Tasks;

using SuppressMessageAttribute = System.Diagnostics.CodeAnalysis.SuppressMessageAttribute;
using Encoding = System.Text.Encoding;
Expand Down Expand Up @@ -267,6 +269,42 @@ public static XDocument Load(Stream stream, LoadOptions options)
}
}

/// <summary>
/// Create a new <see cref="XDocument"/> and initialize its underlying XML tree using
/// the passed <see cref="Stream"/> parameter. Optionally whitespace handling
/// can be preserved.
/// </summary>
/// <remarks>
/// If LoadOptions.PreserveWhitespace is enabled then
/// the underlying <see cref="XmlReaderSettings"/> property <see cref="XmlReaderSettings.IgnoreWhitespace"/>
/// is set to false.
/// </remarks>
/// <param name="stream">
/// A <see cref="Stream"/> containing the raw XML to read into the newly
/// created <see cref="XDocument"/>.
/// </param>
/// <param name="options">
/// A set of <see cref="LoadOptions"/>.
/// </param>
/// <param name="cancellationToken">
/// A cancellation token.
/// </param>
/// <returns>
/// A new <see cref="XDocument"/> containing the contents of the passed in
/// <see cref="Stream"/>.
/// </returns>
public static async Task<XDocument> LoadAsync(Stream stream, LoadOptions options, CancellationToken cancellationToken)
{
XmlReaderSettings rs = GetXmlReaderSettings(options);

rs.Async = true;

using (XmlReader r = XmlReader.Create(stream, rs))
{
return await LoadAsync(r, options, cancellationToken).ConfigureAwait(false);
}
}

/// <summary>
/// Create a new <see cref="XDocument"/> and initialize its underlying XML tree using
/// the passed <see cref="TextReader"/> parameter.
Expand Down Expand Up @@ -314,6 +352,42 @@ public static XDocument Load(TextReader textReader, LoadOptions options)
}
}

/// <summary>
/// Create a new <see cref="XDocument"/> and initialize its underlying XML tree using
/// the passed <see cref="TextReader"/> parameter. Optionally whitespace handling
/// can be preserved.
/// </summary>
/// <remarks>
/// If LoadOptions.PreserveWhitespace is enabled then
/// the <see cref="XmlReaderSettings"/> property <see cref="XmlReaderSettings.IgnoreWhitespace"/>
/// is set to false.
/// </remarks>
/// <param name="textReader">
/// A <see cref="TextReader"/> containing the raw XML to read into the newly
/// created <see cref="XDocument"/>.
/// </param>
/// <param name="options">
/// A set of <see cref="LoadOptions"/>.
/// </param>
/// <param name="cancellationToken">
/// A cancellation token.
/// </param>
/// <returns>
/// A new <see cref="XDocument"/> containing the contents of the passed in
/// <see cref="TextReader"/>.
/// </returns>
public static async Task<XDocument> LoadAsync(TextReader textReader, LoadOptions options, CancellationToken cancellationToken)
{
XmlReaderSettings rs = GetXmlReaderSettings(options);

rs.Async = true;

using (XmlReader r = XmlReader.Create(textReader, rs))
{
return await LoadAsync(r, options, cancellationToken).ConfigureAwait(false);
}
}

/// <summary>
/// Create a new <see cref="XDocument"/> containing the contents of the
/// passed in <see cref="XmlReader"/>.
Expand Down Expand Up @@ -350,6 +424,55 @@ public static XDocument Load(XmlReader reader, LoadOptions options)
{
if (reader == null) throw new ArgumentNullException("reader");
if (reader.ReadState == ReadState.Initial) reader.Read();

XDocument d = InitLoad(reader, options);
d.ReadContentFrom(reader, options);

if (!reader.EOF) throw new InvalidOperationException(SR.InvalidOperation_ExpectedEndOfFile);
if (d.Root == null) throw new InvalidOperationException(SR.InvalidOperation_MissingRoot);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please put the throw statement on its own line to match the coding guidelines.

return d;
}

/// <summary>
/// Create a new <see cref="XDocument"/> containing the contents of the
/// passed in <see cref="XmlReader"/>.
/// </summary>
/// <param name="reader">
/// An <see cref="XmlReader"/> containing the XML to be read into the new
/// <see cref="XDocument"/>.
/// </param>
/// <param name="options">
/// A set of <see cref="LoadOptions"/>.
/// </param>
/// <param name="cancellationToken">
/// A cancellation token.
/// </param>
/// <returns>
/// A new <see cref="XDocument"/> containing the contents of the passed
/// in <see cref="XmlReader"/>.
/// </returns>
public static async Task<XDocument> LoadAsync(XmlReader reader, LoadOptions options, CancellationToken cancellationToken)
{
if (reader == null) throw new ArgumentNullException("reader");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please put the throw statement on its own line to match the coding guidelines.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should really be part of its own non-async method that then delegates to an async method for the actual work so that the usage error propagates out synchronously.

if (reader.ReadState == ReadState.Initial)
{
cancellationToken.ThrowIfCancellationRequested();
await reader.ReadAsync().ConfigureAwait(false);
}

XDocument d = InitLoad(reader, options);
await d.ReadContentFromAsync(reader, options, cancellationToken);

if (!reader.EOF) throw new InvalidOperationException(SR.InvalidOperation_ExpectedEndOfFile);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please put the throw statement on its own line to match the coding guidelines.

if (d.Root == null) throw new InvalidOperationException(SR.InvalidOperation_MissingRoot);
return d;
}

/// <summary>
/// Performs shared initialization between Load and LoadAsync.
/// </summary>
static XDocument InitLoad(XmlReader reader, LoadOptions options)
{
XDocument d = new XDocument();
if ((options & LoadOptions.SetBaseUri) != 0)
{
Expand All @@ -371,9 +494,6 @@ public static XDocument Load(XmlReader reader, LoadOptions options)
{
d.Declaration = new XDeclaration(reader);
}
d.ReadContentFrom(reader, options);
if (!reader.EOF) throw new InvalidOperationException(SR.InvalidOperation_ExpectedEndOfFile);
if (d.Root == null) throw new InvalidOperationException(SR.InvalidOperation_MissingRoot);
return d;
}

Expand Down Expand Up @@ -478,6 +598,40 @@ public void Save(Stream stream, SaveOptions options)
}
}

/// <summary>
/// Output this <see cref="XDocument"/> to a <see cref="Stream"/>.
/// </summary>
/// <param name="stream">
/// The <see cref="Stream"/> to output the XML to.
/// </param>
/// <param name="options">
/// If SaveOptions.DisableFormatting is enabled the output is not indented.
/// If SaveOptions.OmitDuplicateNamespaces is enabled duplicate namespace declarations will be removed.
/// </param>
/// <param name="cancellationToken">A cancellation token.</param>
public async Task SaveAsync(Stream stream, SaveOptions options, CancellationToken cancellationToken)
{
XmlWriterSettings ws = GetXmlWriterSettings(options);

ws.Async = true;

if (declaration != null && !string.IsNullOrEmpty(declaration.Encoding))
{
try
{
ws.Encoding = Encoding.GetEncoding(declaration.Encoding);
}
catch (ArgumentException)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we catching ArgumentException? That is generally not a good idea.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After looking at the documentation I see that what we throw if the encoding cannot be found and you are doing what we already do in Save. While I don't particularly like this approach I also don't see another option so I guess we will have to live with this.

{
}
}

using (XmlWriter w = XmlWriter.Create(stream, ws))
{
await WriteToAsync(w, cancellationToken).ConfigureAwait(false);
}
}

/// <summary>
/// Output this <see cref="XDocument"/> to the passed in <see cref="TextWriter"/>.
/// </summary>
Expand Down Expand Up @@ -516,6 +670,29 @@ public void Save(TextWriter textWriter, SaveOptions options)
}
}

/// <summary>
/// Output this <see cref="XDocument"/> to a <see cref="TextWriter"/>.
/// </summary>
/// <param name="textWriter">
/// The <see cref="TextWriter"/> to output the XML to.
/// </param>
/// <param name="options">
/// If SaveOptions.DisableFormatting is enabled the output is not indented.
/// If SaveOptions.OmitDuplicateNamespaces is enabled duplicate namespace declarations will be removed.
/// </param>
/// <param name="cancellationToken">A cancellation token.</param>
public async Task SaveAsync(TextWriter textWriter, SaveOptions options, CancellationToken cancellationToken)
{
XmlWriterSettings ws = GetXmlWriterSettings(options);

ws.Async = true;

using (XmlWriter w = XmlWriter.Create(textWriter, ws))
{
await WriteToAsync(w, cancellationToken).ConfigureAwait(false);
}
}

/// <summary>
/// Output this <see cref="XDocument"/> to an <see cref="XmlWriter"/>.
/// </summary>
Expand All @@ -527,6 +704,19 @@ public void Save(XmlWriter writer)
WriteTo(writer);
}

/// <summary>
/// Output this <see cref="XDocument"/> to an <see cref="XmlWriter"/>.
/// </summary>
/// <param name="writer">
/// The <see cref="XmlWriter"/> to output the XML to.
/// </param>
/// <param name="cancellationToken">
/// A cancellation token.
/// </param>
public async Task SaveAsync(XmlWriter writer, CancellationToken cancellationToken)
{
await WriteToAsync(writer, cancellationToken).ConfigureAwait(false);
}

/// <summary>
/// Output this <see cref="XDocument"/>'s underlying XML tree to the
Expand Down Expand Up @@ -556,6 +746,42 @@ public override void WriteTo(XmlWriter writer)
writer.WriteEndDocument();
}

/// <summary>
/// Output this <see cref="XDocument"/>'s underlying XML tree to the
/// passed in <see cref="XmlWriter"/>.
/// <seealso cref="XDocument.Save(XmlWriter)"/>
/// </summary>
/// <param name="writer">
/// The <see cref="XmlWriter"/> to output the content of this
/// <see cref="XDocument"/>.
/// </param>
/// <param name="cancellationToken">A cancellation token.</param>
public override async Task WriteToAsync(XmlWriter writer, CancellationToken cancellationToken)
{
if (writer == null) throw new ArgumentNullException("writer");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please put the throw statement on its own line to match the coding guidelines.


cancellationToken.ThrowIfCancellationRequested();

Task tStart;

if (declaration != null && declaration.Standalone == "yes")
{
tStart = writer.WriteStartDocumentAsync(true);
}
else if (declaration != null && declaration.Standalone == "no")
{
tStart = writer.WriteStartDocumentAsync(false);
}
else
{
tStart = writer.WriteStartDocumentAsync();
}

await tStart.ConfigureAwait(false);
await WriteContentToAsync(writer, cancellationToken).ConfigureAwait(false);
await writer.WriteEndDocumentAsync().ConfigureAwait(false);
}

internal override void AddAttribute(XAttribute a)
{
throw new ArgumentException(SR.Argument_AddAttribute);
Expand Down
19 changes: 19 additions & 0 deletions src/System.Xml.XDocument/System/Xml/Linq/XDocumentType.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Threading;
using System.Threading.Tasks;
namespace System.Xml.Linq
{
/// <summary>
Expand Down Expand Up @@ -142,6 +144,23 @@ public override void WriteTo(XmlWriter writer)
writer.WriteDocType(name, publicId, systemId, internalSubset);
}

/// <summary>
/// Write this <see cref="XDocumentType"/> to the passed in <see cref="XmlWriter"/>.
/// </summary>
/// <param name="writer">
/// The <see cref="XmlWriter"/> to write this <see cref="XDocumentType"/> to.
/// </param>
/// <param name="cancellationToken">
/// A cancellation token.
/// </param>
public override async Task WriteToAsync(XmlWriter writer, CancellationToken cancellationToken)
{
if (writer == null) throw new ArgumentNullException("writer");

cancellationToken.ThrowIfCancellationRequested();
await writer.WriteDocTypeAsync(name, publicId, systemId, internalSubset).ConfigureAwait(false);
}

internal override XNode CloneNode()
{
return new XDocumentType(this);
Expand Down
Loading