Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add SpellChecker sample #123

Merged
merged 1 commit into from
Feb 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="all" />
<PackageReference Include="Nerdbank.GitVersioning" Version="3.3.37" PrivateAssets="all" />
<PackageReference Include="Nullable" Version="1.3.0" PrivateAssets="all" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.261" PrivateAssets="all" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.321" PrivateAssets="all" />
</ItemGroup>

<ItemGroup>
Expand Down
7 changes: 7 additions & 0 deletions Microsoft.Windows.CsWin32.sln
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Win32MetaGeneration", "src\
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GenerationSandbox.Tests", "test\GenerationSandbox.Tests\GenerationSandbox.Tests.csproj", "{7E8A5179-F94C-410F-8BBE-FDAAA95A19C3}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SpellChecker", "test\SpellChecker\SpellChecker.csproj", "{744BE74F-8C4A-49E8-9683-52D987224285}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -65,6 +67,10 @@ Global
{7E8A5179-F94C-410F-8BBE-FDAAA95A19C3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7E8A5179-F94C-410F-8BBE-FDAAA95A19C3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7E8A5179-F94C-410F-8BBE-FDAAA95A19C3}.Release|Any CPU.Build.0 = Release|Any CPU
{744BE74F-8C4A-49E8-9683-52D987224285}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{744BE74F-8C4A-49E8-9683-52D987224285}.Debug|Any CPU.Build.0 = Debug|Any CPU
{744BE74F-8C4A-49E8-9683-52D987224285}.Release|Any CPU.ActiveCfg = Release|Any CPU
{744BE74F-8C4A-49E8-9683-52D987224285}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -75,6 +81,7 @@ Global
{EB7D0834-4236-408F-B172-64FB45FF643A} = {9E154A29-1796-4B85-BD81-B6A385D8FF71}
{6638957D-09ED-47C1-86B9-5D2DFD0FE625} = {9E154A29-1796-4B85-BD81-B6A385D8FF71}
{7E8A5179-F94C-410F-8BBE-FDAAA95A19C3} = {36CCE840-6FE5-4DB9-A8D5-8CF3CB6D342A}
{744BE74F-8C4A-49E8-9683-52D987224285} = {36CCE840-6FE5-4DB9-A8D5-8CF3CB6D342A}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {E3944F6A-384B-4B0F-B93F-3BD513DC57BD}
Expand Down
1 change: 0 additions & 1 deletion test/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory)../, Directory.Build.props))\Directory.Build.props" Condition=" '$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory)../, Directory.Build.props))' != '' " />

<PropertyGroup>
<TargetFrameworks>net5.0;netcoreapp3.1;net472</TargetFrameworks>
<IsPackable>false</IsPackable>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
</PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<Import Project="..\..\src\Microsoft.Windows.CsWin32\build\Microsoft.Windows.CsWin32.props" />

<PropertyGroup>
<TargetFrameworks>net5.0;netcoreapp3.1;net472</TargetFrameworks>
<RootNamespace />
</PropertyGroup>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net5.0;netcoreapp3.1;net472</TargetFrameworks>
<RootNamespace />
</PropertyGroup>

Expand Down
7 changes: 7 additions & 0 deletions test/SpellChecker/NativeMethods.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
CoCreateInstance
CoTaskMemFree
SpellCheckerFactory
ISpellCheckerFactory
ISpellChecker
CLSCTX
S_FALSE
31 changes: 31 additions & 0 deletions test/SpellChecker/PInvoke.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace Microsoft.Windows.Sdk
{
using System;
using System.Runtime.InteropServices;

internal partial class PInvoke
{
/// <inheritdoc cref="CoCreateInstance(System.Guid*, IUnknown*, uint, System.Guid*, void**)"/>
/// <seealso href="https://github.com/microsoft/CsWin32/issues/103" />
internal static unsafe HRESULT CoCreateInstance<T>(in System.Guid rclsid, IUnknown* pUnkOuter, uint dwClsContext, in System.Guid riid, out T* ppv)
AArnott marked this conversation as resolved.
Show resolved Hide resolved
where T : unmanaged
{
HRESULT hr = CoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, out void* o);
ppv = (T*)o;
return hr;
}

/// <inheritdoc cref="Marshal.ThrowExceptionForHR(int, IntPtr)" />
/// <returns>The value from <paramref name="errorCode"/> if it does not reflect an error.</returns>
/// <seealso cref="Marshal.ThrowExceptionForHR(int, IntPtr)"/>
/// <seealso href="https://github.com/microsoft/CsWin32/issues/119" />
internal static HRESULT ThrowOnFailure(this HRESULT errorCode, IntPtr errorInfo = default)
{
Marshal.ThrowExceptionForHR(errorCode, errorInfo);
return errorCode;
}
}
}
98 changes: 98 additions & 0 deletions test/SpellChecker/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.Collections.Generic;
using Microsoft.Windows.Sdk;
using static Microsoft.Windows.Sdk.Constants;
using static Microsoft.Windows.Sdk.PInvoke;

unsafe
{
CoCreateInstance(
typeof(SpellCheckerFactory).GUID,
null,
(uint)CLSCTX.CLSCTX_INPROC_SERVER, // https://github.com/microsoft/win32metadata/issues/185
typeof(ISpellCheckerFactory).GUID,
out ISpellCheckerFactory* spellCheckerFactory).ThrowOnFailure();

spellCheckerFactory->IsSupported(
"en-US",
out bool supported).ThrowOnFailure();

if (!supported)
{
return;
}

spellCheckerFactory->CreateSpellChecker(
"en-US",
out ISpellChecker* spellChecker).ThrowOnFailure();

var text = @"""Cann I I haev some?""";

Console.WriteLine(@"Check {0}", text);

spellChecker->Check(
text,
out IEnumSpellingError* errors).ThrowOnFailure();

while (true)
{
if (errors->Next(out ISpellingError* error).ThrowOnFailure() == S_FALSE)
{
break;
}

error->get_StartIndex(out uint startIndex).ThrowOnFailure();
error->get_Length(out uint length).ThrowOnFailure();

var word = text.Substring((int)startIndex, (int)length);

error->get_CorrectiveAction(out CORRECTIVE_ACTION action).ThrowOnFailure();

switch (action)
{
case CORRECTIVE_ACTION.CORRECTIVE_ACTION_DELETE:
Console.WriteLine(@"Delete ""{0}""", word);
break;
case CORRECTIVE_ACTION.CORRECTIVE_ACTION_REPLACE:
// KNOWN ISSUE: ushort will be changed to string (https://github.com/microsoft/CsWin32/issues/121)
error->get_Replacement(out ushort* replacement).ThrowOnFailure();
Console.WriteLine(@"Replace ""{0}"" with ""{1}""", word, new string((char*)replacement));
CoTaskMemFree(replacement);
break;
case CORRECTIVE_ACTION.CORRECTIVE_ACTION_GET_SUGGESTIONS:
var l = new List<string>();
spellChecker->Suggest(word, out IEnumString* suggestions).ThrowOnFailure();
while (true)
{
// KNOWN ISSUE: ushort will be changed to string (https://github.com/microsoft/CsWin32/issues/121)
ushort* suggestion;
if (suggestions->Next(1, &suggestion, null).ThrowOnFailure() != 0)
{
break;
}

l.Add(new string((char*)suggestion));
CoTaskMemFree(suggestion);
}

suggestions->Release();
Console.WriteLine(@"Suggest replacing ""{0}"" with:", word);
foreach (var s in l)
{
Console.WriteLine("\t{0}", s);
}

break;
default:
break;
}

error->Release();
}

errors->Release();
spellChecker->Release();
}
21 changes: 21 additions & 0 deletions test/SpellChecker/SpellChecker.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\src\Microsoft.Windows.CsWin32\build\Microsoft.Windows.CsWin32.props" />

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.Windows.CsWin32\Microsoft.Windows.CsWin32.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
<Analyzer Include="$(RepoRootPath)\bin\Microsoft.Windows.CsWin32\$(Configuration)\netstandard2.0\System.Text.Json.dll" />
<Analyzer Include="$(RepoRootPath)\bin\Microsoft.Windows.CsWin32\$(Configuration)\netstandard2.0\Microsoft.Bcl.AsyncInterfaces.dll" />
<Analyzer Include="$(RepoRootPath)\bin\Microsoft.Windows.CsWin32\$(Configuration)\netstandard2.0\System.Text.Encodings.Web.dll" />
<Analyzer Include="$(RepoRootPath)\bin\Microsoft.Windows.CsWin32\$(Configuration)\netstandard2.0\YamlDotNet.dll" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Windows.SDK.Win32Metadata" Version="$(MetadataVersion)" GeneratePathProperty="true" PrivateAssets="none" />
<PackageReference Include="System.Memory" Version="4.5.4" />
</ItemGroup>

</Project>