├── .gitignore ├── README ├── license.txt └── src ├── .nuget ├── NuGet.Config ├── NuGet.exe └── NuGet.targets ├── ItemTemplates ├── LayoutPage │ ├── LayoutPage.csproj │ ├── LayoutPage.spark │ ├── LayoutPage.vstemplate │ ├── Properties │ │ └── AssemblyInfo.cs │ └── SparkIcon.png ├── ViewPage │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── SparkIcon.png │ ├── ViewPage.csproj │ ├── ViewPage.spark │ └── ViewPage.vstemplate └── ViewPageWithLayout │ ├── Properties │ └── AssemblyInfo.cs │ ├── SparkIcon.png │ ├── ViewPageWithLayout.csproj │ ├── ViewPageWithLayout.spark │ └── ViewPageWithLayout.vstemplate ├── SparkSense.Tests ├── Compiling │ └── WhenCompilingIncompleteCode.cs ├── Parsing │ ├── CachingViewFolderTests.cs │ ├── ParseContextChunkTests.cs │ ├── ParseContextNodeTests.cs │ ├── ParseMultipleNodeTests.cs │ ├── ParseSingleNodeTests.cs │ ├── ProjectExplorerTests.cs │ ├── SparkSyntaxTests.cs │ ├── ViewExplorerTests.cs │ └── WhenParsingIncompleteCode.cs ├── Properties │ └── AssemblyInfo.cs ├── Scenarios │ ├── Scenario.cs │ ├── SyntaxCompilationScenario.cs │ ├── SyntaxParsingScenario.cs │ ├── TypeCompletionScenario.cs │ └── TypeResolutionScenario.cs ├── SparkSense.Tests.Views │ └── Shared │ │ ├── Application.spark │ │ ├── _SharedPartial.spark │ │ └── test.spark ├── SparkSense.Tests.csproj ├── SpecificationExtensions.cs ├── StatementCompletion │ ├── AttributeCompletionSetTests.cs │ ├── CompletionSessionTests.cs │ ├── ElementCompletionSetTests.cs │ ├── ExpressionCompletionSetTests.cs │ └── TextViewCreationTests.cs ├── TypeCompletion │ ├── WhenNavigatingThroughMembers.cs │ ├── WhenNavigatingThroughNameSpaces.cs │ └── WhenTriggeringTypeCompletion.cs ├── TypeResolution │ ├── WhenResolvingInstanceMembers.cs │ ├── WhenResolvingMethods.cs │ ├── WhenResolvingStaticMembers.cs │ ├── WhenResolvingTriggerTypes.cs │ └── WhenResolvingTypes.cs └── packages.config ├── SparkSense.gpState ├── SparkSense.ncrunchsolution ├── SparkSense.sln ├── SparkSense ├── ContentType │ └── SparkFileAndContentTypes.cs ├── Parser │ ├── CompletionBuilder.cs │ ├── CompletionBuilderExtensions.cs │ ├── CompletionGrammar.cs │ └── CompletionSyntaxProvider.cs ├── Parsing │ ├── CachingViewFolder.cs │ ├── Constants.cs │ ├── IProjectExplorer.cs │ ├── IViewExplorer.cs │ ├── ParsingExtensions.cs │ ├── ProjectExplorer.cs │ ├── SparkSyntax.cs │ ├── TypeNavigator.cs │ └── ViewExplorer.cs ├── Presenter │ ├── SparkSensePresenter.cs │ ├── SparkSensePresenterListener.cs │ ├── SparkSenseView.xaml │ └── SparkSenseView.xaml.cs ├── Properties │ └── AssemblyInfo.cs ├── Resources │ ├── Class.png │ ├── Event.png │ ├── Field.png │ ├── Method.png │ ├── Namespace.png │ ├── Property.png │ ├── SparkAttribute.png │ ├── SparkContentName.png │ ├── SparkElement.png │ ├── SparkGlobalVariable.png │ ├── SparkLocalVariable.png │ ├── SparkMacro.png │ ├── SparkMacroParameter.png │ ├── SparkPartial.png │ ├── SparkPartialParameter.png │ └── SparkSenseViewResources.xaml ├── SignatureRecognition │ ├── SparkSignatureHelpCommand.cs │ ├── SparkSignatureHelpCommandListener.cs │ ├── SparkSignatureHelpSource.cs │ ├── SparkSignatureHelpSourceProvider.cs │ ├── SparkTagParameter.cs │ └── SparkTagSignature.cs ├── SparkIcon.png ├── SparkLogo.png ├── SparkSense.csproj ├── SparkServiceProvider.cs ├── StatementCompletion │ ├── CompletionExtensions.cs │ ├── CompletionListener.cs │ ├── CompletionSessionManager.cs │ ├── CompletionSets │ │ ├── AttributeCompletionSet.cs │ │ ├── CompletionSetFactory.cs │ │ ├── ElementCompletionSet.cs │ │ └── ExpressionCompletionSet.cs │ ├── CompletionSource.cs │ ├── KeyPressInterceptor.cs │ └── ViewCreationListener.cs ├── license.txt ├── packages.config └── source.extension.vsixmanifest └── packages ├── NUnit.2.6.1 ├── NUnit.2.6.1.nupkg ├── lib │ ├── nunit.framework.dll │ └── nunit.framework.xml └── license.txt ├── RhinoMocks.3.6.1 ├── RhinoMocks.3.6.1.nupkg └── lib │ └── net │ ├── Rhino.Mocks.dll │ └── Rhino.Mocks.xml ├── Spark.1.7.2.0 ├── Spark.1.7.2.0.nupkg └── lib │ ├── NET35 │ └── Spark.dll │ └── NET40 │ └── Spark.dll ├── fasterflect.2.1.0 ├── fasterflect.2.1.0.nupkg └── lib │ ├── net35 │ ├── Fasterflect.XML │ └── Fasterflect.dll │ └── net40 │ ├── Fasterflect.XML │ └── Fasterflect.dll └── repositories.config /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore the output folder. 2 | build 3 | 4 | # Ignore all */bin/ and */obj/ folders... 5 | bin/ 6 | obj/ 7 | 8 | # ...except the root bin folder (used for build tools and etc.). 9 | !/bin/ 10 | 11 | # Ignore backup files. 12 | *.orig 13 | 14 | # Ignore all Visual Studio generated files. 15 | *.suo 16 | *.user 17 | *.ncb 18 | _ReSharper.* 19 | 20 | # Ignore all MonoDevelop generated files. 21 | *.userprefs 22 | *.pidb 23 | 24 | # Ignore all Operating System generated files. 25 | Thumbs.db 26 | 27 | # Ignore all Test Suite status files. 28 | TestResult.xml 29 | *.VisualState.xml 30 | 31 | # Ignore some other things, too. 32 | src/Tools/SparkLanguagePackage/*_i.c 33 | src/Tools/SparkLanguagePackage/*_i.h 34 | src/Tools/SparkLanguagePackage/*_p.c 35 | src/Tools/SparkLanguagePackage/PackageLoadKey.h 36 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | SparkSense is a plugin for Visual Studio 2010 that enables various tooling support and productivity features when using Spark as a View Engine for various MVC frameworks including ASP.NET MVC, FubuMVC, Monorail, OpenRasta to name a few. It also works when using Spark as a stand-alone templating engine in VS2010. 2 | 3 | The source code has been moved out of the core Spark library due to key differences in use and applicability and deployment cycles. In addition to providing better visibility for the product, it also takes a dependency on the Visual Studio 2010 SDK which means it cannot be part of the Spark Core primary solution without forcing any developers only interestd in Spark Core to install the SDK. It also also allows those developers who wish to learn about Visual Studio Extensibility without needing to concern themselves with the code base of Spark Core iteself. -------------------------------------------------------------------------------- /src/.nuget/NuGet.Config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/.nuget/NuGet.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SparkViewEngine/SparkSense/08c46f516a03d7276350c1cf7ceea043673008a6/src/.nuget/NuGet.exe -------------------------------------------------------------------------------- /src/.nuget/NuGet.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildProjectDirectory)\..\ 5 | 6 | 7 | false 8 | 9 | 10 | false 11 | 12 | 13 | true 14 | 15 | 16 | false 17 | 18 | 19 | 20 | 21 | 25 | 26 | 27 | 28 | 29 | $([System.IO.Path]::Combine($(SolutionDir), ".nuget")) 30 | $([System.IO.Path]::Combine($(ProjectDir), "packages.config")) 31 | $([System.IO.Path]::Combine($(SolutionDir), "packages")) 32 | 33 | 34 | 35 | 36 | $(SolutionDir).nuget 37 | packages.config 38 | $(SolutionDir)packages 39 | 40 | 41 | 42 | 43 | $(NuGetToolsPath)\nuget.exe 44 | @(PackageSource) 45 | 46 | "$(NuGetExePath)" 47 | mono --runtime=v4.0.30319 $(NuGetExePath) 48 | 49 | $(TargetDir.Trim('\\')) 50 | 51 | -RequireConsent 52 | 53 | $(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(RequireConsentSwitch) -o "$(PackagesDir)" 54 | $(NuGetCommand) pack "$(ProjectPath)" -p Configuration=$(Configuration) -o "$(PackageOutputDir)" -symbols 55 | 56 | 57 | 58 | RestorePackages; 59 | $(BuildDependsOn); 60 | 61 | 62 | 63 | 64 | $(BuildDependsOn); 65 | BuildPackage; 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 79 | 80 | 83 | 84 | 85 | 86 | 88 | 89 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 140 | 141 | 142 | 143 | -------------------------------------------------------------------------------- /src/ItemTemplates/LayoutPage/LayoutPage.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 7 | {080A3968-BA97-48B2-AC8C-19AC327E62C6} 8 | Library 9 | Properties 10 | LayoutPage 11 | LayoutPage 12 | v4.0 13 | 512 14 | false 15 | false 16 | false 17 | false 18 | false 19 | false 20 | false 21 | false 22 | false 23 | false 24 | 25 | 26 | true 27 | full 28 | false 29 | bin\Debug\ 30 | DEBUG;TRACE 31 | prompt 32 | 4 33 | 34 | 35 | pdbonly 36 | true 37 | bin\Release\ 38 | TRACE 39 | prompt 40 | 4 41 | 42 | 43 | 44 | False 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | Web\Spark 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 74 | -------------------------------------------------------------------------------- /src/ItemTemplates/LayoutPage/LayoutPage.spark: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | ${ViewBag.Title} 8 | 9 | 10 |
11 | 12 |
13 | 14 | -------------------------------------------------------------------------------- /src/ItemTemplates/LayoutPage/LayoutPage.vstemplate: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Spark Layout Page 5 | Layout Page with Spark syntax (spark) 6 | SparkIcon.png 7 | CSharp 8 | 3 9 | true 10 | LayoutPage.spark 11 | 12 | 13 | LayoutPage.spark 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/ItemTemplates/LayoutPage/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("LayoutPage")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("LayoutPage")] 13 | [assembly: AssemblyCopyright("Copyright © 2012")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("76e075d5-e0ee-4aaa-8212-f0a5e485ece6")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/ItemTemplates/LayoutPage/SparkIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SparkViewEngine/SparkSense/08c46f516a03d7276350c1cf7ceea043673008a6/src/ItemTemplates/LayoutPage/SparkIcon.png -------------------------------------------------------------------------------- /src/ItemTemplates/ViewPage/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("ViewPage")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ViewPage")] 13 | [assembly: AssemblyCopyright("Copyright © 2012")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("6d5d7a21-089b-48b4-981a-19f1c03cc05d")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/ItemTemplates/ViewPage/SparkIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SparkViewEngine/SparkSense/08c46f516a03d7276350c1cf7ceea043673008a6/src/ItemTemplates/ViewPage/SparkIcon.png -------------------------------------------------------------------------------- /src/ItemTemplates/ViewPage/ViewPage.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 7 | {977A1109-A90E-40DE-B976-04A406B9114D} 8 | Library 9 | Properties 10 | ViewPage 11 | ViewPage 12 | v4.0 13 | 512 14 | false 15 | false 16 | false 17 | false 18 | false 19 | false 20 | false 21 | false 22 | false 23 | false 24 | 25 | 26 | true 27 | full 28 | false 29 | bin\Debug\ 30 | DEBUG;TRACE 31 | prompt 32 | 4 33 | 34 | 35 | pdbonly 36 | true 37 | bin\Release\ 38 | TRACE 39 | prompt 40 | 4 41 | 42 | 43 | 44 | False 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | Web\Spark 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 74 | -------------------------------------------------------------------------------- /src/ItemTemplates/ViewPage/ViewPage.spark: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 |
13 | 14 | -------------------------------------------------------------------------------- /src/ItemTemplates/ViewPage/ViewPage.vstemplate: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Spark View Page 5 | View Page with Spark syntax (spark) 6 | SparkIcon.png 7 | CSharp 8 | 3 9 | true 10 | ViewPage.spark 11 | 12 | 13 | ViewPage.spark 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/ItemTemplates/ViewPageWithLayout/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("ViewPageWithLayout")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ViewPageWithLayout")] 13 | [assembly: AssemblyCopyright("Copyright © 2012")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("92199a7f-d4fa-4162-bbc7-29267b045e18")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/ItemTemplates/ViewPageWithLayout/SparkIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SparkViewEngine/SparkSense/08c46f516a03d7276350c1cf7ceea043673008a6/src/ItemTemplates/ViewPageWithLayout/SparkIcon.png -------------------------------------------------------------------------------- /src/ItemTemplates/ViewPageWithLayout/ViewPageWithLayout.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 7 | {24C1E236-C53F-47E8-AA1B-68FE5264C934} 8 | Library 9 | Properties 10 | ViewPageWithLayout 11 | ViewPageWithLayout 12 | v4.0 13 | 512 14 | false 15 | false 16 | false 17 | false 18 | false 19 | false 20 | false 21 | false 22 | false 23 | false 24 | 25 | 26 | true 27 | full 28 | false 29 | bin\Debug\ 30 | DEBUG;TRACE 31 | prompt 32 | 4 33 | 34 | 35 | pdbonly 36 | true 37 | bin\Release\ 38 | TRACE 39 | prompt 40 | 4 41 | 42 | 43 | 44 | False 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | Web\Spark 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 74 | -------------------------------------------------------------------------------- /src/ItemTemplates/ViewPageWithLayout/ViewPageWithLayout.spark: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/ItemTemplates/ViewPageWithLayout/ViewPageWithLayout.vstemplate: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Spark View Page with Layout 5 | View Page with Layout with Spark syntax (spark) 6 | SparkIcon.png 7 | CSharp 8 | 3 9 | true 10 | ViewPage.spark 11 | 12 | 13 | ViewPageWithLayout.spark 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/SparkSense.Tests/Compiling/WhenCompilingIncompleteCode.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using Spark.Compiler; 3 | using SparkSense.Tests.Scenarios; 4 | 5 | namespace SparkSense.Tests.Compiling 6 | { 7 | public class WhenCompilingIncompleteCode : SyntaxCompilationScenario 8 | { 9 | public WhenCompilingIncompleteCode() 10 | { 11 | GivenSomeContentToCompile(@"
${user.
"); 12 | WhenCompilingIntoCodeSnippitChunks(); 13 | } 14 | 15 | [Test] 16 | public void ShouldContainAnExpressionChunkBetweenTwoLiteralChunks() 17 | { 18 | TheParsedChunks[0] 19 | .ShouldBeOfType() 20 | .Text 21 | .ShouldBe("
"); 22 | 23 | TheParsedChunks[1] 24 | .ShouldBeOfType() 25 | .Code.ToString() 26 | .ShouldBe("user."); 27 | 28 | TheParsedChunks[2] 29 | .ShouldBeOfType() 30 | .Text 31 | .ShouldBe("
"); 32 | } 33 | 34 | [Test] 35 | public void ShouldReturnANumberOfCompiledChunks() 36 | { 37 | TheParsedChunks 38 | .ShouldNotBeNull() 39 | .ShouldHaveCount(3); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /src/SparkSense.Tests/Parsing/CachingViewFolderTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NUnit.Framework; 3 | using SparkSense.Parsing; 4 | using System.IO; 5 | 6 | namespace SparkSense.Tests.Parsing 7 | { 8 | [TestFixture] 9 | public class CachingViewFolderTests 10 | { 11 | private const string ROOT_VIEW_PATH = "SparkSense.Tests.Views"; 12 | 13 | [Test] 14 | public void ShouldLoadFromDiskIfPathNotInCache() 15 | { 16 | string contents = String.Empty; 17 | var cache = new CachingViewFolder(ROOT_VIEW_PATH); 18 | var content = cache.GetViewSource("Shared\\Application.spark"); 19 | 20 | using (TextReader reader = new StreamReader(content.OpenViewStream())) 21 | contents = reader.ReadToEnd(); 22 | 23 | Assert.That(contents.Contains("no header by default")); 24 | } 25 | 26 | [Test] 27 | public void ShouldLoadFromDiskIfPathInCacheWithNullData() 28 | { 29 | string path = "Shared\\Application.spark"; 30 | string contents = String.Empty; 31 | var cache = new CachingViewFolder(ROOT_VIEW_PATH); 32 | cache.Add(path); 33 | var content = cache.GetViewSource(path); 34 | 35 | using (TextReader reader = new StreamReader(content.OpenViewStream())) 36 | contents = reader.ReadToEnd(); 37 | 38 | Assert.That(contents.Contains("no header by default")); 39 | } 40 | 41 | [Test] 42 | public void ShouldAllowCacheContentToBeReplaced() 43 | { 44 | string path = "Shared\\test.spark"; 45 | string contents = String.Empty; 46 | var cache = new CachingViewFolder(ROOT_VIEW_PATH); 47 | cache.Add(path); 48 | string newContent = "This is new content"; 49 | 50 | cache.SetViewSource(path, newContent); 51 | var content = cache.GetViewSource(path); 52 | using (TextReader reader = new StreamReader(content.OpenViewStream())) 53 | contents = reader.ReadToEnd(); 54 | 55 | Assert.That(contents.Contains(newContent)); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/SparkSense.Tests/Parsing/ParseContextChunkTests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using Spark.Compiler; 3 | using SparkSense.Parsing; 4 | using System; 5 | 6 | namespace SparkSense.Tests.Parsing 7 | { 8 | [TestFixture] 9 | public class ParseContextChunkTests 10 | { 11 | [Test] 12 | public void ShouldReturnContentChunkGivenPositionAfterContentElementColon() 13 | { 14 | Type nodeType = SparkSyntax.ParseContextChunk("
", position: 14); 15 | 16 | Assert.That(nodeType, Is.EqualTo(typeof(ContentChunk))); 17 | } 18 | 19 | [Test] 20 | public void ShouldReturnContentChunkGivenPositionInsideDoubleQuotes() 21 | { 22 | Type nodeType = SparkSyntax.ParseContextChunk("
", position: 20); 23 | 24 | Assert.That(nodeType, Is.EqualTo(typeof(ContentChunk))); 25 | } 26 | 27 | [Test] 28 | public void ShouldReturnContentChunkGivenPositionInsideSingleQuotes() 29 | { 30 | Type nodeType = SparkSyntax.ParseContextChunk("
", position: 20); 31 | 32 | Assert.That(nodeType, Is.EqualTo(typeof(ContentChunk))); 33 | } 34 | 35 | [Test] 36 | public void ShouldReturnMacroChunkGivenPositionAfterMacroElementColon() 37 | { 38 | Type nodeType = SparkSyntax.ParseContextChunk("
", position: 12); 39 | 40 | Assert.That(nodeType, Is.EqualTo(typeof(MacroChunk))); 41 | } 42 | 43 | [Test] 44 | public void ShouldReturnMacroChunkGivenPositionInsideDoubleQuotes() 45 | { 46 | Type nodeType = SparkSyntax.ParseContextChunk("
", position: 18); 47 | 48 | Assert.That(nodeType, Is.EqualTo(typeof(MacroChunk))); 49 | } 50 | 51 | [Test] 52 | public void ShouldReturnMacroChunkGivenPositionInsideSingleQuotes() 53 | { 54 | Type nodeType = SparkSyntax.ParseContextChunk("
", position: 18); 55 | 56 | Assert.That(nodeType, Is.EqualTo(typeof(MacroChunk))); 57 | } 58 | 59 | [Test] 60 | public void ShouldReturnRenderChunkGivenPositionAfterRenderElementColon() 61 | { 62 | Type nodeType = SparkSyntax.ParseContextChunk("
", position: 13); 63 | 64 | Assert.That(nodeType, Is.EqualTo(typeof(RenderSectionChunk))); 65 | } 66 | 67 | [Test] 68 | public void ShouldReturnRenderChunkGivenPositionInsideDoubleQuotes() 69 | { 70 | Type nodeType = SparkSyntax.ParseContextChunk("
", position: 22); 71 | 72 | Assert.That(nodeType, Is.EqualTo(typeof(RenderPartialChunk))); 73 | } 74 | 75 | [Test] 76 | public void ShouldReturnRenderChunkGivenPositionInsideSingleQuotes() 77 | { 78 | Type nodeType = SparkSyntax.ParseContextChunk("
", position: 22); 79 | 80 | Assert.That(nodeType, Is.EqualTo(typeof(RenderPartialChunk))); 81 | } 82 | 83 | [Test] 84 | public void ShouldReturnUseChunkGivenPositionAfterUseElementColon() 85 | { 86 | Type nodeType = SparkSyntax.ParseContextChunk("
", position: 10); 87 | 88 | Assert.That(nodeType, Is.EqualTo(typeof(UseContentChunk))); 89 | } 90 | 91 | [Test] 92 | public void ShouldReturnUseChunkGivenPositionInsideDoubleQuotes() 93 | { 94 | Type nodeType = SparkSyntax.ParseContextChunk("
", position: 19); 95 | 96 | Assert.That(nodeType, Is.EqualTo(typeof(UseContentChunk))); 97 | } 98 | 99 | [Test] 100 | public void ShouldReturnUseChunkGivenPositionInsideSingleQuotes() 101 | { 102 | Type nodeType = SparkSyntax.ParseContextChunk("
", position: 19); 103 | 104 | Assert.That(nodeType, Is.EqualTo(typeof(UseContentChunk))); 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/SparkSense.Tests/Parsing/ParseContextNodeTests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using Spark.Parser.Markup; 3 | using SparkSense.Parsing; 4 | using System; 5 | using Spark.Compiler; 6 | 7 | namespace SparkSense.Tests.Parsing 8 | { 9 | [TestFixture] 10 | public class ParseContextNodeTests 11 | { 12 | [Test] 13 | public void ShouldReturnAttributeNodeGivenPositionAtStartOfAttribute() 14 | { 15 | var nodeType = SparkSyntax.ParseContext("
", position: 10); 16 | 17 | Assert.That(nodeType, Is.EqualTo(typeof(AttributeNode))); 18 | } 19 | 20 | [Test] 21 | public void ShouldReturnAttributeNodeGivenPositionInQuotes() 22 | { 23 | var nodeType = SparkSyntax.ParseContext("
", position: 19); 24 | 25 | Assert.That(nodeType, Is.EqualTo(typeof(AttributeNode))); 26 | } 27 | 28 | [Test] 29 | public void ShouldReturnElementNodeGivenPositionAfterColonInElementName() 30 | { 31 | var nodeType = SparkSyntax.ParseContext("
", position: 10); 32 | var chunkType = SparkSyntax.ParseContextChunk("
", position: 10); 33 | 34 | Assert.That(nodeType, Is.EqualTo(typeof(ElementNode))); 35 | Assert.That(chunkType, Is.EqualTo(typeof(UseContentChunk))); 36 | } 37 | 38 | [Test] 39 | public void ShouldReturnElementNodeGivenPositionAtStartOfNewlyOpenedElement() 40 | { 41 | Type nodeType = SparkSyntax.ParseContext("
<
", position: 6); 42 | 43 | Assert.That(nodeType, Is.EqualTo(typeof(ElementNode))); 44 | } 45 | 46 | [Test] 47 | public void ShouldReturnElementNodeGivenPositionInNameOfElement() 48 | { 49 | Type nodeType = SparkSyntax.ParseContext("
", position: 8); 50 | 51 | Assert.That(nodeType, Is.EqualTo(typeof(ElementNode))); 52 | } 53 | 54 | [Test] 55 | public void ShouldReturnExpressionNodeGivenPositionAfterDollarOpeningBrace() 56 | { 57 | Type nodeType = SparkSyntax.ParseContext("${", position: 2); 58 | 59 | Assert.That(nodeType, Is.EqualTo(typeof(ExpressionNode))); 60 | } 61 | 62 | [Test] 63 | public void ShouldReturnExpressionNodeGivenPositionAfterExclamationOpeningBrace() 64 | { 65 | Type nodeType = SparkSyntax.ParseContext("!{", position: 2); 66 | 67 | Assert.That(nodeType, Is.EqualTo(typeof(ExpressionNode))); 68 | } 69 | 70 | [Test] 71 | public void ShouldReturnTextNodeGivenPositionAfterOpeningBrace() 72 | { 73 | Type nodeType = SparkSyntax.ParseContext("{", position: 1); 74 | 75 | Assert.That(nodeType, Is.EqualTo(typeof(TextNode))); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/SparkSense.Tests/Parsing/ParseMultipleNodeTests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using Spark.Compiler.NodeVisitors; 3 | using Spark.Parser.Markup; 4 | using SparkSense.Parsing; 5 | 6 | namespace SparkSense.Tests.Parsing 7 | { 8 | [TestFixture] 9 | public class ParseMultipleNodeTests 10 | { 11 | [Test] 12 | public void ShouldParseIntoMultipleNodes() 13 | { 14 | var nodes = SparkSyntax.ParseNodes("
"); 15 | var visitor = new SpecialNodeVisitor(new VisitorContext()); 16 | visitor.Accept(nodes); 17 | 18 | Assert.That(visitor.Nodes.Count, Is.EqualTo(3)); 19 | Assert.That(visitor.Nodes[0], Is.InstanceOf(typeof(ElementNode))); 20 | Assert.That(visitor.Nodes[1], Is.InstanceOf(typeof(SpecialNode))); 21 | Assert.That(visitor.Nodes[2], Is.InstanceOf(typeof(EndElementNode))); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/SparkSense.Tests/Parsing/ParseSingleNodeTests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using Spark.Parser.Markup; 3 | using SparkSense.Parsing; 4 | using System; 5 | 6 | namespace SparkSense.Tests.Parsing 7 | { 8 | [TestFixture] 9 | public class ParseSingleNodeTests 10 | { 11 | [Test] 12 | public void ShouldReturnElementNodeGivenPositionInsideAnyElement() 13 | { 14 | var node = SparkSyntax.ParseNode("
", position: 1); 15 | 16 | Assert.That(node, Is.InstanceOf(typeof(ElementNode))); 17 | Assert.That(((ElementNode)node).Name, Is.EqualTo("div")); 18 | } 19 | 20 | [Test] 21 | public void ShouldReturnNullGivenPositionAtTheBeginning() 22 | { 23 | var node = SparkSyntax.ParseNode("
", position: 0); 24 | 25 | Assert.That(node, Is.Null); 26 | } 27 | 28 | [Test] 29 | public void ShouldReturnNullGivenPositionAtTheEnd() 30 | { 31 | var node = SparkSyntax.ParseNode("
", position: 11); 32 | 33 | Assert.That(node, Is.Null); 34 | } 35 | 36 | [Test] 37 | public void ShouldReturnNullGivenPositionInAnEndElement() 38 | { 39 | var node = SparkSyntax.ParseNode("
", position: 10); 40 | 41 | Assert.That(node, Is.Null); 42 | } 43 | 44 | [Test] 45 | public void ShouldReturnNullGivenPositionBetweenNodes() 46 | { 47 | var node = SparkSyntax.ParseNode("
", position: 5); 48 | 49 | Assert.That(node, Is.Null); 50 | } 51 | 52 | [Test] 53 | public void ShouldReturnNullGivenPositionAtEndOfLine() 54 | { 55 | var node = SparkSyntax.ParseNode(String.Format("
{0}
", Environment.NewLine), position: 27); 56 | 57 | Assert.That(node, Is.Null); 58 | } 59 | 60 | [Test] 61 | public void ShouldReturnElementNodeGivenPositionInsideACompleteElement() 62 | { 63 | var node = SparkSyntax.ParseNode("
", position: 6); 64 | 65 | Assert.That(node, Is.InstanceOf(typeof(ElementNode))); 66 | Assert.That(((ElementNode)node).Name, Is.EqualTo("use")); 67 | Assert.That(((ElementNode)node).Attributes.Count, Is.EqualTo(1)); 68 | Assert.That(((ElementNode)node).Attributes[0].Name, Is.EqualTo("content")); 69 | Assert.That(((ElementNode)node).Attributes[0].Value, Is.EqualTo("main")); 70 | } 71 | 72 | [Test] 73 | public void ShouldReturnElementNodeGivenAnUnclosedElementWithValidAttributes() 74 | { 75 | var node = SparkSyntax.ParseNode("
", position: 10); 76 | 77 | Assert.That(node, Is.InstanceOf(typeof(ElementNode))); 78 | Assert.That(((ElementNode)node).Name, Is.EqualTo("use")); 79 | Assert.That(((ElementNode)node).Attributes.Count, Is.EqualTo(1)); 80 | Assert.That(((ElementNode)node).Attributes[0].Name, Is.EqualTo("content")); 81 | Assert.That(((ElementNode)node).Attributes[0].Value, Is.EqualTo("main")); 82 | } 83 | 84 | [Test] 85 | public void ShouldReturnElementNodeGivenAnUnclosedElementAtTheEndOfTheContent() 86 | { 87 | var node = SparkSyntax.ParseNode("", position: 1); 14 | 15 | Node sparkNode; 16 | var isSparkNode = SparkSyntax.IsSpecialNode(node, out sparkNode); 17 | 18 | Assert.That(isSparkNode); 19 | Assert.IsNotNull(sparkNode); 20 | Assert.That(sparkNode, Is.InstanceOf(typeof(SpecialNode))); 21 | } 22 | 23 | [Test] 24 | public void IsSparkNodeShouldReturnSpecialNodeForClosedEmptyElement() 25 | { 26 | var node = SparkSyntax.ParseNode("", position: 1); 27 | 28 | Node sparkNode; 29 | var isSparkNode = SparkSyntax.IsSpecialNode(node, out sparkNode); 30 | 31 | Assert.That(isSparkNode); 32 | Assert.IsNotNull(sparkNode); 33 | Assert.That(sparkNode, Is.InstanceOf(typeof(SpecialNode))); 34 | } 35 | 36 | [Test] 37 | public void IsSparkNodeShouldReturnSpecialNodeForUnclosedElement() 38 | { 39 | var node = SparkSyntax.ParseNode("", position: 1); 40 | 41 | Node sparkNode; 42 | var isSparkNode = SparkSyntax.IsSpecialNode(node, out sparkNode); 43 | 44 | Assert.That(isSparkNode); 45 | Assert.IsNotNull(sparkNode); 46 | Assert.That(sparkNode, Is.InstanceOf(typeof(SpecialNode))); 47 | } 48 | 49 | [Test] 50 | public void IsSparkNodeShouldReturnElementNodeIfNotSparkSyntax() 51 | { 52 | var node = SparkSyntax.ParseNode("
", position: 1); 53 | 54 | Node elementNode; 55 | var isSparkNode = SparkSyntax.IsSpecialNode(node, out elementNode); 56 | 57 | Assert.That(!isSparkNode); 58 | Assert.IsNotNull(elementNode); 59 | Assert.That(elementNode, Is.InstanceOf(typeof(ElementNode))); 60 | } 61 | 62 | [Test] 63 | public void ShouldResultInAttributeNameContext() 64 | { 65 | Assert.IsTrue(SparkSyntax.IsPositionInAttributeName("
", 11)); 66 | Assert.IsFalse(SparkSyntax.IsPositionInAttributeValue("
", 11)); 67 | 68 | Assert.IsTrue(SparkSyntax.IsPositionInAttributeName("
", 11)); 69 | Assert.IsFalse(SparkSyntax.IsPositionInAttributeValue("
", 11)); 70 | 71 | Assert.IsTrue(SparkSyntax.IsPositionInAttributeName("
", 19)); 72 | Assert.IsFalse(SparkSyntax.IsPositionInAttributeValue("
", 19)); 73 | 74 | Assert.IsTrue(SparkSyntax.IsPositionInAttributeName("
", 19)); 75 | Assert.IsFalse(SparkSyntax.IsPositionInAttributeValue("
", 19)); 76 | } 77 | 78 | [Test] 79 | public void ShouldResultInAttributeValueContext() 80 | { 81 | Assert.IsTrue(SparkSyntax.IsPositionInAttributeValue("
", 16)); 82 | Assert.IsFalse(SparkSyntax.IsPositionInAttributeName("
", 16)); 83 | 84 | Assert.IsTrue(SparkSyntax.IsPositionInAttributeValue("
", 25)); 85 | Assert.IsFalse(SparkSyntax.IsPositionInAttributeName("
", 25)); 86 | 87 | Assert.IsTrue(SparkSyntax.IsPositionInAttributeValue("
", 30)); 88 | Assert.IsFalse(SparkSyntax.IsPositionInAttributeName("
", 30)); 89 | 90 | Assert.IsTrue(SparkSyntax.IsPositionInAttributeValue("
", 22)); 91 | Assert.IsFalse(SparkSyntax.IsPositionInAttributeName("
", 22)); 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/SparkSense.Tests/Parsing/WhenParsingIncompleteCode.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using Spark.Parser.Markup; 3 | using SparkSense.Tests.Scenarios; 4 | 5 | namespace SparkSense.Tests.Parsing 6 | { 7 | public class WhenParsingIncompleteCode : SyntaxParsingScenario 8 | { 9 | [Test] 10 | public void ShouldCorrectlyParseIncompleteCodeAfterBangSyntax() 11 | { 12 | GivenSomeContentToParse("!{user."); 13 | WhenParsingForIncompleteCode(); 14 | TheParsedExpressionNode 15 | .ShouldNotBeNull() 16 | .ShouldBeOfType() 17 | .Code.ToString() 18 | .ShouldBe("user."); 19 | } 20 | 21 | [Test] 22 | public void ShouldCorrectlyParseIncompleteCodeAfterDollarSyntax() 23 | { 24 | GivenSomeContentToParse("${user."); 25 | WhenParsingForIncompleteCode(); 26 | TheParsedExpressionNode 27 | .ShouldNotBeNull() 28 | .ShouldBeOfType() 29 | .Code.ToString() 30 | .ShouldBe("user."); 31 | } 32 | 33 | [Test] 34 | public void ShouldCorrectlyParseIncompleteCodeWhenFollowedByAnotherNode() 35 | { 36 | GivenSomeContentToParse("${user.name
"); 37 | WhenParsingForAnyNode(); 38 | TheParsedExpressionNode 39 | .ShouldNotBeNull() 40 | .ShouldBeOfType() 41 | .Code.ToString() 42 | .ShouldBe("user.name"); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /src/SparkSense.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("SparkSense.Tests")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("Microsoft")] 11 | [assembly: AssemblyProduct("SparkSense.Tests")] 12 | [assembly: AssemblyCopyright("Copyright © Microsoft 2010")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("96696988-fba0-4e6c-bf1f-c807ec005efe")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /src/SparkSense.Tests/Scenarios/Scenario.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | 3 | namespace SparkSense.Tests.Scenarios 4 | { 5 | [TestFixture] 6 | public class Scenario 7 | { 8 | #region Setup/Teardown 9 | 10 | [SetUp] 11 | protected virtual void SetUp() 12 | { 13 | } 14 | 15 | [TearDown] 16 | protected virtual void TearDown() 17 | { 18 | } 19 | 20 | #endregion 21 | 22 | [Test] 23 | public void ShouldNotBeIgnoredByTestRunner() { } 24 | } 25 | } -------------------------------------------------------------------------------- /src/SparkSense.Tests/Scenarios/SyntaxCompilationScenario.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Spark.Compiler; 3 | using Spark.Compiler.NodeVisitors; 4 | using Spark.FileSystem; 5 | using SparkSense.Parser; 6 | 7 | namespace SparkSense.Tests.Scenarios 8 | { 9 | public class SyntaxCompilationScenario : Scenario 10 | { 11 | private CompletionSyntaxProvider _syntaxProvider; 12 | private VisitorContext _context; 13 | 14 | protected IList TheParsedChunks { get; private set; } 15 | 16 | protected void GivenSomeContentToCompile(string content) 17 | { 18 | _syntaxProvider = new CompletionSyntaxProvider(); 19 | _context = new VisitorContext 20 | {ViewFolder = new InMemoryViewFolder {{"Home\\index.spark", @"
${user.
"}}}; 21 | } 22 | 23 | protected void WhenCompilingIntoCodeSnippitChunks() 24 | { 25 | TheParsedChunks = _syntaxProvider.GetChunks(_context, "Home\\index.spark"); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /src/SparkSense.Tests/Scenarios/SyntaxParsingScenario.cs: -------------------------------------------------------------------------------- 1 | using Spark.Parser; 2 | using Spark.Parser.Markup; 3 | using SparkSense.Parser; 4 | 5 | namespace SparkSense.Tests.Scenarios 6 | { 7 | public class SyntaxParsingScenario : Scenario 8 | { 9 | private CompletionGrammar _grammar; 10 | private Position _sourceContent; 11 | protected ExpressionNode TheParsedExpressionNode { get; private set; } 12 | 13 | protected Position Source(string content) 14 | { 15 | return new Position(new SourceContext(content)); 16 | } 17 | 18 | protected void GivenSomeContentToParse(string content) 19 | { 20 | _grammar = new CompletionGrammar(); 21 | _sourceContent = Source(content); 22 | } 23 | 24 | protected void WhenParsingForAnyNode() 25 | { 26 | TheParsedExpressionNode = _grammar.AnyNode(_sourceContent).Value as ExpressionNode; 27 | } 28 | 29 | protected void WhenParsingForIncompleteCode() 30 | { 31 | TheParsedExpressionNode = null; 32 | ParseResult result = _grammar.IncompleteCode(_sourceContent); 33 | TheParsedExpressionNode = result == null ? null : result.Value; 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /src/SparkSense.Tests/Scenarios/TypeCompletionScenario.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Microsoft.VisualStudio.Language.Intellisense; 4 | using SparkSense.Parser; 5 | using SparkSense.Parsing; 6 | 7 | namespace SparkSense.Tests.Scenarios 8 | { 9 | public class TypeCompletionScenario : TypeResolutionScenario 10 | { 11 | protected IEnumerable TheCompletionList { get; private set; } 12 | 13 | protected void WhenTriggeringAnInitialCompletion() 14 | { 15 | WhenTriggeringACompletion(string.Empty); 16 | } 17 | 18 | protected void WhenTriggeringACompletion(string codeSnippit) 19 | { 20 | var completionBuilder = new CompletionBuilder(TheViewExplorer); 21 | WhenLookingUpTriggerTypes(); 22 | TheCompletionList = completionBuilder.ToCompletionList(codeSnippit); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /src/SparkSense.Tests/Scenarios/TypeResolutionScenario.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.ComponentModel.Design; 5 | using System.Reflection; 6 | using Rhino.Mocks; 7 | using SparkSense.Parsing; 8 | 9 | namespace SparkSense.Tests.Scenarios 10 | { 11 | public class TypeResolutionScenario : Scenario 12 | { 13 | protected Type TheResolvedType { get; private set; } 14 | 15 | protected IEnumerable TheResolvedTriggerTypes { get; private set; } 16 | 17 | protected IEnumerable TheResolvedMembers { get; private set; } 18 | 19 | protected IEnumerable TheResolvedMethods { get; private set; } 20 | 21 | protected string TheRemainingCode { get; private set; } 22 | 23 | public TypeNavigator TheTypeNavigator { get; private set; } 24 | 25 | protected IViewExplorer TheViewExplorer { get; set; } 26 | 27 | protected void GivenReferencedTypes(IEnumerable types) 28 | { 29 | TheTypeNavigator = new TypeNavigator(types); 30 | TheViewExplorer = MockRepository.GenerateMock(); 31 | TheViewExplorer.Expect(x => x.GetTypeNavigator()).Return(TheTypeNavigator); 32 | TheViewExplorer.Expect(x => x.GetLocalVariableChunks()).Return(null); 33 | TheViewExplorer.Expect(x => x.GetViewDataVariableChunks()).Return(null); 34 | } 35 | 36 | protected void WhenLookingUpTriggerTypes() 37 | { 38 | TheResolvedTriggerTypes = TheTypeNavigator.GetTriggerTypes(); 39 | } 40 | 41 | protected void WhenLookingUpStaticMembers() 42 | { 43 | TheResolvedMembers = TheTypeNavigator.GetStaticMembers(); 44 | } 45 | 46 | protected void WhenLookingUpInstanceMembers() 47 | { 48 | TheResolvedMembers = TheTypeNavigator.GetInstanceMembers(); 49 | } 50 | 51 | protected void WhenLookingUpMethods(string methodName) 52 | { 53 | TheResolvedMethods = TheTypeNavigator.GetMethodByName(methodName); 54 | } 55 | 56 | protected void WhenLookingUpSomeCode(string codeSnippit) 57 | { 58 | Type resolvedType; 59 | string remainingCode; 60 | if (TheTypeNavigator.TryResolveType(TheViewExplorer, codeSnippit, out resolvedType, out remainingCode)) 61 | TheResolvedType = resolvedType; 62 | TheRemainingCode = remainingCode; 63 | } 64 | 65 | protected class StubPrivateType 66 | { 67 | public string StubInstanceField; 68 | 69 | public string StubInstanceProperty { get; set; } 70 | 71 | public string StubInstanceMethod() 72 | { 73 | return string.Empty; 74 | } 75 | } 76 | 77 | public class StubTypeWithNoStatics 78 | { 79 | public string StubInstanceField; 80 | 81 | public string StubInstanceProperty { get; set; } 82 | 83 | public string StubInstanceMethod() 84 | { 85 | return string.Empty; 86 | } 87 | } 88 | 89 | public class StubType 90 | { 91 | public static string StubStaticField; 92 | 93 | public string StubInstanceField; 94 | 95 | public static string StubStaticProperty { get; set; } 96 | 97 | public string StubInstanceProperty { get; set; } 98 | 99 | public StubType StubTypeInstanceProperty { get; set; } 100 | 101 | public static string StubStaticMethod() 102 | { 103 | return string.Empty; 104 | } 105 | 106 | public string StubInstanceMethod() 107 | { 108 | return string.Empty; 109 | } 110 | 111 | public string StubMethodWithParameters(string param1) 112 | { 113 | return string.Empty; 114 | } 115 | 116 | public string StubMethodWithParameters(string param1, int param2) 117 | { 118 | return string.Empty; 119 | } 120 | 121 | public string StubMethodWithParameters(string param1, int param2, StubType param3) 122 | { 123 | return string.Empty; 124 | } 125 | } 126 | } 127 | } -------------------------------------------------------------------------------- /src/SparkSense.Tests/SparkSense.Tests.Views/Shared/Application.spark: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | ${title} 5 | 6 | 7 | 12 |
13 | 14 |
15 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/SparkSense.Tests/SparkSense.Tests.Views/Shared/_SharedPartial.spark: -------------------------------------------------------------------------------- 1 | Some shared content -------------------------------------------------------------------------------- /src/SparkSense.Tests/SparkSense.Tests.Views/Shared/test.spark: -------------------------------------------------------------------------------- 1 | 
2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
NameType
${user.Name}${user.UserType}
21 |
-------------------------------------------------------------------------------- /src/SparkSense.Tests/SpecificationExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using NUnit.Framework; 5 | 6 | namespace SparkSense.Tests 7 | { 8 | public static class SpecificationExtensions 9 | { 10 | public static void ShouldBeTrue(this bool value) 11 | { 12 | Assert.That(value); 13 | } 14 | 15 | public static T ShouldNotBeNull(this T value) where T : class 16 | { 17 | Assert.IsNotNull(value); 18 | return value; 19 | } 20 | 21 | public static T ShouldBe(this T actualValue, T expectedValue) 22 | { 23 | Assert.That(actualValue, Is.EqualTo(expectedValue)); 24 | return actualValue; 25 | } 26 | 27 | public static T ShouldBeOfType(this object value) where T : class 28 | { 29 | Assert.That(value.GetType(), Is.EqualTo(typeof(T))); 30 | return value as T; 31 | } 32 | 33 | public static IEnumerable ShouldHaveCount(this IEnumerable values, int count) 34 | { 35 | Assert.AreEqual(count, values.Count()); 36 | return values; 37 | } 38 | 39 | public static IEnumerable ShouldHaveCount(this IEnumerable values, int count, Func predicate) 40 | { 41 | ShouldHaveCount(values.Where(predicate), count); 42 | return values; 43 | } 44 | 45 | public static T ShouldContain(this IEnumerable values, Func predicate) 46 | { 47 | var found = values.FirstOrDefault(predicate); 48 | Assert.IsNotNull(found, string.Format("Expected item was not found in the values supplied.")); 49 | return found; 50 | } 51 | 52 | public static IEnumerable ShouldNotContain(this IEnumerable values, Func predicate) 53 | { 54 | var found = values.FirstOrDefault(predicate); 55 | Assert.IsNull(found, "Unexpected item was found in the values supplied."); 56 | return values; 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /src/SparkSense.Tests/StatementCompletion/AttributeCompletionSetTests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using Microsoft.VisualStudio.Text; 4 | using NUnit.Framework; 5 | using Rhino.Mocks; 6 | using SparkSense.Parsing; 7 | using SparkSense.StatementCompletion.CompletionSets; 8 | 9 | namespace SparkSense.Tests.StatementCompletion 10 | { 11 | [TestFixture] 12 | public class AttributeCompletionSetTests 13 | { 14 | private IViewExplorer _mockViewExplorer; 15 | private ITextSnapshot _stubSnapshot; 16 | private ITrackingSpan _stubTrackingSpan; 17 | private IViewExplorer _stubViewExplorer; 18 | 19 | [SetUp] 20 | public void Setup() 21 | { 22 | _mockViewExplorer = MockRepository.GenerateMock(); 23 | _stubSnapshot = MockRepository.GenerateStub(); 24 | _stubViewExplorer = MockRepository.GenerateStub(); 25 | _stubTrackingSpan = MockRepository.GenerateStub(); 26 | } 27 | 28 | [TearDown] 29 | public void Cleanup() 30 | { 31 | _mockViewExplorer.VerifyAllExpectations(); 32 | _mockViewExplorer = null; 33 | } 34 | 35 | private SnapshotPoint GetSnapShotPoint(string content, int position) 36 | { 37 | _stubSnapshot.Stub(x => x.Length).Return(content.Length); 38 | _stubSnapshot.Stub(x => x.GetText()).Return(content); 39 | return new SnapshotPoint(_stubSnapshot, position); 40 | } 41 | 42 | [Test] 43 | public void ShouldReturnSpecialNodeAttributes() 44 | { 45 | var point = GetSnapShotPoint("
", 10); 46 | var completionSet = CompletionSetFactory.GetCompletionSetFor(point, _stubTrackingSpan, _stubViewExplorer); 47 | var completions = completionSet.Completions.ToList(); 48 | 49 | Assert.That(completionSet, Is.InstanceOf(typeof(AttributeCompletionSet))); 50 | Assert.That(completions.Count, Is.EqualTo(7)); 51 | Assert.That(completions.Exists(a => a.DisplayText == "content")); 52 | Assert.That(completions.Exists(a => a.DisplayText == "master")); 53 | } 54 | 55 | [Test] 56 | public void ShouldReturnContentNamesAsAttributeValues() 57 | { 58 | var point = GetSnapShotPoint("
", 20); 59 | _mockViewExplorer.Expect(x => x.GetContentNames()).Return(new List { "title", "head", "view", "footer" }); 60 | 61 | var completionSet = CompletionSetFactory.GetCompletionSetFor(point, _stubTrackingSpan, _mockViewExplorer); 62 | var completions = completionSet.Completions.ToList(); 63 | 64 | Assert.That(completionSet, Is.InstanceOf(typeof(AttributeCompletionSet))); 65 | Assert.That(completions.Count, Is.EqualTo(4)); 66 | Assert.That(completions.Exists(a => a.DisplayText == "title")); 67 | Assert.That(completions.Exists(a => a.DisplayText == "footer")); 68 | } 69 | 70 | [Test] 71 | public void ShouldReturnVariableNamesAsAttributeValues() 72 | { 73 | var point = GetSnapShotPoint("
", 15); 74 | _mockViewExplorer.Expect(x => x.GetLocalVariables()).Return(new List { "x", "y" }); 75 | _mockViewExplorer.Expect(x => x.GetGlobalVariables()).Return(new List { "g1", "g2" }); 76 | 77 | var completionSet = CompletionSetFactory.GetCompletionSetFor(point, _stubTrackingSpan, _mockViewExplorer); 78 | var completions = completionSet.Completions.ToList(); 79 | 80 | Assert.That(completionSet, Is.InstanceOf(typeof(AttributeCompletionSet))); 81 | Assert.That(completions.Count, Is.EqualTo(4)); 82 | Assert.That(completions.Exists(a => a.DisplayText == "x")); 83 | Assert.That(completions.Exists(a => a.DisplayText == "y")); 84 | Assert.That(completions.Exists(a => a.DisplayText == "g1")); 85 | Assert.That(completions.Exists(a => a.DisplayText == "g2")); 86 | } 87 | 88 | [Test] 89 | public void ShouldReturnMasterNamesAsAttributeValues() 90 | { 91 | var point = GetSnapShotPoint("
", 18); 92 | _mockViewExplorer.Expect(x => x.GetPossibleMasterLayouts()).Return(new List { "html", "master" }); 93 | 94 | var completionSet = CompletionSetFactory.GetCompletionSetFor(point, _stubTrackingSpan, _mockViewExplorer); 95 | var completions = completionSet.Completions.ToList(); 96 | 97 | Assert.That(completionSet, Is.InstanceOf(typeof(AttributeCompletionSet))); 98 | Assert.That(completions.Count, Is.EqualTo(2)); 99 | Assert.That(completions.Exists(a => a.DisplayText == "html")); 100 | Assert.That(completions.Exists(a => a.DisplayText == "master")); 101 | } 102 | 103 | [Test] 104 | public void ShouldReturnAttributeNameContextWhenPositionedAfterElementName() 105 | { 106 | var point = GetSnapShotPoint("
", 10); 107 | 108 | var completionSet = (AttributeCompletionSet)CompletionSetFactory.GetCompletionSetFor(point, _stubTrackingSpan, _stubViewExplorer); 109 | Assert.That(completionSet.AttributeContext, Is.EqualTo(AttributeContexts.Name)); 110 | } 111 | 112 | [Test] 113 | public void ShouldReturnAttributeNameContextWhenPositionedAfterPreviousClosedAttribute() 114 | { 115 | var point = GetSnapShotPoint("
", 16); 116 | 117 | var completionSet = (AttributeCompletionSet)CompletionSetFactory.GetCompletionSetFor(point, _stubTrackingSpan, _stubViewExplorer); 118 | Assert.That(completionSet.AttributeContext, Is.EqualTo(AttributeContexts.Name)); 119 | } 120 | 121 | [Test] 122 | public void ShouldReturnAttributeValueContextWhenPositionedInsideEmptyQuotes() 123 | { 124 | var point = GetSnapShotPoint("
", 13); 125 | 126 | var completionSet = (AttributeCompletionSet)CompletionSetFactory.GetCompletionSetFor(point, _stubTrackingSpan, _stubViewExplorer); 127 | Assert.That(completionSet.AttributeContext, Is.EqualTo(AttributeContexts.Value)); 128 | } 129 | 130 | [Test] 131 | public void ShouldReturnAttributeValueContextWhenPositionedAfterASpaceInsideQuotes() 132 | { 133 | var point = GetSnapShotPoint("
", 25); 134 | 135 | var completionSet = (AttributeCompletionSet)CompletionSetFactory.GetCompletionSetFor(point, _stubTrackingSpan, _stubViewExplorer); 136 | Assert.That(completionSet.AttributeContext, Is.EqualTo(AttributeContexts.Value)); 137 | } 138 | 139 | [Test] 140 | public void ShouldReturnAttributeValueContextWhenPositionedAnywhereInsideQuotes() 141 | { 142 | var point = GetSnapShotPoint("
", 16); 143 | 144 | var completionSet = (AttributeCompletionSet)CompletionSetFactory.GetCompletionSetFor(point, _stubTrackingSpan, _stubViewExplorer); 145 | Assert.That(completionSet.AttributeContext, Is.EqualTo(AttributeContexts.Value)); 146 | } 147 | 148 | [Test] 149 | public void ShouldReturnAttributeValueContextWhenPositionedOnAnyAttributeInsideQuotes() 150 | { 151 | var point = GetSnapShotPoint("
", 22); 152 | 153 | var completionSet = (AttributeCompletionSet)CompletionSetFactory.GetCompletionSetFor(point, _stubTrackingSpan, _stubViewExplorer); 154 | Assert.That(completionSet.AttributeContext, Is.EqualTo(AttributeContexts.Value)); 155 | } 156 | } 157 | } -------------------------------------------------------------------------------- /src/SparkSense.Tests/StatementCompletion/CompletionSessionTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.Language.Intellisense; 3 | using Microsoft.VisualStudio.Text.Editor; 4 | using NUnit.Framework; 5 | using Rhino.Mocks; 6 | using SparkSense.StatementCompletion; 7 | using Microsoft.VisualStudio.Text.Operations; 8 | using Microsoft.VisualStudio.Text; 9 | 10 | namespace SparkSense.Tests.StatementCompletion 11 | { 12 | [TestFixture] 13 | public class CompletionSessionTests 14 | { 15 | [Test] 16 | [ExpectedException(typeof(ArgumentNullException))] 17 | public void ShouldThrowIfConfigIsNull() 18 | { 19 | new CompletionSessionManager( 20 | null, 21 | MockRepository.GenerateStub(), 22 | MockRepository.GenerateStub() 23 | ); 24 | } 25 | 26 | [Test] 27 | [ExpectedException(typeof(ArgumentNullException))] 28 | public void ShouldThrowIfTextViewIsNull() 29 | { 30 | new CompletionSessionManager( 31 | MockRepository.GenerateStub(), 32 | null, 33 | MockRepository.GenerateStub() 34 | ); 35 | } 36 | 37 | [Test] 38 | [ExpectedException(typeof(ArgumentNullException))] 39 | public void ShouldThrowIfTextNavigatorIsNull() 40 | { 41 | new CompletionSessionManager( 42 | MockRepository.GenerateStub(), 43 | MockRepository.GenerateStub(), 44 | null 45 | ); 46 | } 47 | 48 | [Test] 49 | public void ListenerShouldAttemptToGetAnInstanceOfTheProjectExplorer() 50 | { 51 | var mockServiceProvider = MockRepository.GenerateMock(); 52 | var stubTextBuffer = MockRepository.GenerateStub(); 53 | var listener = new CompletionListener { ServiceProvider = mockServiceProvider }; 54 | 55 | mockServiceProvider.Expect(x => x.ProjectExplorer).Return(null); 56 | listener.TryCreateCompletionSource(stubTextBuffer); 57 | 58 | mockServiceProvider.VerifyAllExpectations(); 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /src/SparkSense.Tests/StatementCompletion/ElementCompletionSetTests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using Microsoft.VisualStudio.Language.Intellisense; 4 | using Microsoft.VisualStudio.Text; 5 | using NUnit.Framework; 6 | using Rhino.Mocks; 7 | using SparkSense.Parsing; 8 | using SparkSense.StatementCompletion.CompletionSets; 9 | 10 | namespace SparkSense.Tests.StatementCompletion 11 | { 12 | [TestFixture] 13 | public class ElementCompletionSetTests 14 | { 15 | private ICompletionSession _stubSession; 16 | private ITextBuffer _stubTextBuffer; 17 | private ITrackingSpan _stubTrackingSpan; 18 | private IViewExplorer _stubViewExplorer; 19 | private ITrackingPoint _stubTrackingPoint; 20 | private ITextSnapshot _stubSnapshot; 21 | 22 | [SetUp] 23 | public void Setup() 24 | { 25 | _stubSession = MockRepository.GenerateStub(); 26 | _stubTextBuffer = MockRepository.GenerateStub(); 27 | _stubViewExplorer = MockRepository.GenerateStub(); 28 | _stubTrackingPoint = MockRepository.GenerateStub(); 29 | _stubTrackingSpan = MockRepository.GenerateStub(); 30 | _stubSnapshot = MockRepository.GenerateStub(); 31 | 32 | _stubTextBuffer.Stub(x => x.CurrentSnapshot).Return(_stubSnapshot); 33 | _stubSession.Stub(x => x.GetTriggerPoint(_stubTextBuffer)).Return(_stubTrackingPoint); 34 | _stubTrackingPoint.Stub(x => x.GetPoint(_stubSnapshot)).Return(new SnapshotPoint(_stubSnapshot, 0)); 35 | _stubViewExplorer.Stub(x => x.GetRelatedPartials()).Return(new List()); 36 | } 37 | 38 | [Test] 39 | public void ShouldReturnSparkSpecialNodes() 40 | { 41 | var set = CompletionSetFactory.Create(new SnapshotPoint(_stubSnapshot, 0), _stubTrackingSpan, _stubViewExplorer); 42 | List elementList = set.Completions.ToList(); 43 | 44 | Assert.That(elementList.Exists(c => c.DisplayText == "var")); 45 | Assert.That(elementList.Exists(c => c.DisplayText == "def")); 46 | Assert.That(elementList.Exists(c => c.DisplayText == "default")); 47 | Assert.That(elementList.Exists(c => c.DisplayText == "global")); 48 | Assert.That(elementList.Exists(c => c.DisplayText == "viewdata")); 49 | Assert.That(elementList.Exists(c => c.DisplayText == "set")); 50 | Assert.That(elementList.Exists(c => c.DisplayText == "for")); 51 | Assert.That(elementList.Exists(c => c.DisplayText == "test")); 52 | Assert.That(elementList.Exists(c => c.DisplayText == "if")); 53 | Assert.That(elementList.Exists(c => c.DisplayText == "else")); 54 | Assert.That(elementList.Exists(c => c.DisplayText == "elseif")); 55 | Assert.That(elementList.Exists(c => c.DisplayText == "content")); 56 | Assert.That(elementList.Exists(c => c.DisplayText == "use")); 57 | Assert.That(elementList.Exists(c => c.DisplayText == "macro")); 58 | Assert.That(elementList.Exists(c => c.DisplayText == "render")); 59 | Assert.That(elementList.Exists(c => c.DisplayText == "segment")); 60 | Assert.That(elementList.Exists(c => c.DisplayText == "cache")); 61 | } 62 | 63 | [Test] 64 | public void ShouldLookForRelatedPartials() 65 | { 66 | var mockViewExplorer = MockRepository.GenerateMock(); 67 | 68 | mockViewExplorer.Expect(x => x.GetRelatedPartials()).Return(new List { "partial1", "partial2" }); 69 | 70 | var set = CompletionSetFactory.Create(new SnapshotPoint(), null, mockViewExplorer); 71 | var elementList = set.Completions.ToList(); 72 | Assert.That(elementList.Exists(c => c.DisplayText == "partial1")); 73 | Assert.That(elementList.Exists(c => c.DisplayText == "partial2")); 74 | 75 | mockViewExplorer.VerifyAllExpectations(); 76 | } 77 | } 78 | } -------------------------------------------------------------------------------- /src/SparkSense.Tests/StatementCompletion/ExpressionCompletionSetTests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using Microsoft.VisualStudio.Language.Intellisense; 4 | using Microsoft.VisualStudio.Text; 5 | using NUnit.Framework; 6 | using Rhino.Mocks; 7 | using SparkSense.Parsing; 8 | using SparkSense.StatementCompletion.CompletionSets; 9 | 10 | namespace SparkSense.Tests.StatementCompletion 11 | { 12 | [TestFixture] 13 | public class ExpressionCompletionSetTests 14 | { 15 | #region Setup/Teardown 16 | 17 | [SetUp] 18 | public void Setup() 19 | { 20 | _mockViewExplorer = MockRepository.GenerateMock(); 21 | _stubSnapshot = MockRepository.GenerateStub(); 22 | _stubViewExplorer = MockRepository.GenerateStub(); 23 | _stubTrackingSpan = MockRepository.GenerateStub(); 24 | } 25 | 26 | [TearDown] 27 | public void Cleanup() 28 | { 29 | _mockViewExplorer.VerifyAllExpectations(); 30 | _mockViewExplorer = null; 31 | } 32 | 33 | #endregion 34 | 35 | private IViewExplorer _mockViewExplorer; 36 | private ITextSnapshot _stubSnapshot; 37 | private ITrackingSpan _stubTrackingSpan; 38 | private IViewExplorer _stubViewExplorer; 39 | 40 | private SnapshotPoint GetSnapShotPoint(string content, int position) 41 | { 42 | _stubSnapshot.Stub(x => x.Length).Return(content.Length); 43 | _stubSnapshot.Stub(x => x.GetText()).Return(content); 44 | return new SnapshotPoint(_stubSnapshot, position); 45 | } 46 | 47 | [Test, Ignore("Not ready for this yet")] 48 | public void ShouldHaveAListOfTypes() 49 | { 50 | SnapshotPoint point = GetSnapShotPoint("${", 2); 51 | CompletionSet completionSet = CompletionSetFactory.GetCompletionSetFor(point, _stubTrackingSpan, 52 | _stubViewExplorer); 53 | List completions = completionSet.Completions.ToList(); 54 | 55 | Assert.That(completionSet, Is.InstanceOf(typeof (ExpressionCompletionSet))); 56 | Assert.That(completions.Count, Is.EqualTo(7)); 57 | Assert.That(completions.Exists(a => a.DisplayText == "System")); 58 | Assert.That(completions.Exists(a => a.DisplayText == "Spark")); 59 | } 60 | 61 | [Test, Ignore("Not ready for this yet")] 62 | public void ShouldHaveAListOfVariables() 63 | { 64 | SnapshotPoint point = GetSnapShotPoint("${", 2); 65 | CompletionSet completionSet = CompletionSetFactory.GetCompletionSetFor(point, _stubTrackingSpan, 66 | _stubViewExplorer); 67 | List completions = completionSet.Completions.ToList(); 68 | 69 | Assert.That(completionSet, Is.InstanceOf(typeof (ExpressionCompletionSet))); 70 | Assert.That(completions.Count, Is.EqualTo(7)); 71 | Assert.That(completions.Exists(a => a.DisplayText == "System")); 72 | Assert.That(completions.Exists(a => a.DisplayText == "Spark")); 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /src/SparkSense.Tests/StatementCompletion/TextViewCreationTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.Editor; 3 | using Microsoft.VisualStudio.Text.Editor; 4 | using Microsoft.VisualStudio.TextManager.Interop; 5 | using NUnit.Framework; 6 | using Rhino.Mocks; 7 | using SparkSense.StatementCompletion; 8 | using Microsoft.VisualStudio.Utilities; 9 | using Microsoft.VisualStudio.Text; 10 | using Microsoft.VisualStudio.Text.Operations; 11 | using Microsoft.VisualStudio.Language.Intellisense; 12 | 13 | namespace SparkSense.Tests.StatementCompletion 14 | { 15 | [TestFixture] 16 | public class TextViewCreationTests 17 | { 18 | [Test] 19 | public void ListenerShouldAttemptToGetAnInstanceOfTheWpfTextView() 20 | { 21 | var listener = new ViewCreationListener(); 22 | var mockAdapterFactoryService = MockRepository.GenerateMock(); 23 | var mockTextView = MockRepository.GenerateMock(); 24 | var mockWpfTextView = MockRepository.GenerateMock(); 25 | var mockTextNav = MockRepository.GenerateStub(); 26 | var mockProperties = MockRepository.GenerateStub(); 27 | var mockBuffer = MockRepository.GenerateStub(); 28 | var mockBroker = MockRepository.GenerateStub(); 29 | var mockTextStructureNav = MockRepository.GenerateStub(); 30 | 31 | listener.AdaptersFactoryService = mockAdapterFactoryService; 32 | listener.TextNavigator = mockTextNav; 33 | listener.CompletionBroker = mockBroker; 34 | mockAdapterFactoryService.Expect(x => x.GetWpfTextView(mockTextView)).Return(mockWpfTextView); 35 | mockWpfTextView.Stub(x => x.Properties).Return(mockProperties); 36 | mockWpfTextView.Stub(x => x.TextBuffer).Return(mockBuffer); 37 | mockTextNav.Stub(x => x.GetTextStructureNavigator(mockBuffer)).Return(mockTextStructureNav); 38 | 39 | listener.VsTextViewCreated(mockTextView); 40 | 41 | mockAdapterFactoryService.VerifyAllExpectations(); 42 | } 43 | 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/SparkSense.Tests/TypeCompletion/WhenNavigatingThroughMembers.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using SparkSense.Tests.Scenarios; 3 | 4 | namespace SparkSense.Tests.TypeCompletion 5 | { 6 | public class WhenNavigatingThroughMembers : TypeCompletionScenario 7 | { 8 | public WhenNavigatingThroughMembers() 9 | { 10 | GivenReferencedTypes(new[] { typeof(StubType) }); 11 | } 12 | 13 | [Test] 14 | public void ShouldFindInitialObjectMembers() 15 | { 16 | WhenTriggeringACompletion("StubType."); 17 | TheCompletionList.ShouldContain(c => c.DisplayText == "StubStaticProperty"); 18 | } 19 | 20 | [Test] 21 | public void ShouldFindInitialObjectMembersWithPartialText() 22 | { 23 | WhenTriggeringACompletion("StubType.St"); 24 | TheCompletionList.ShouldContain(c => c.DisplayText == "StubStaticProperty"); 25 | } 26 | 27 | [Test] 28 | public void ShouldDrillDownToObjectMembers() 29 | { 30 | WhenTriggeringACompletion("StubType.StubStaticProperty."); 31 | TheCompletionList.ShouldContain(c => c.DisplayText == "ToLower"); 32 | } 33 | 34 | [Test] 35 | public void ShouldDrillDownToObjectMembersWithPartialText() 36 | { 37 | WhenTriggeringACompletion("StubType.StubStaticProperty.Spl"); 38 | TheCompletionList.ShouldContain(c => c.DisplayText == "ToLower"); 39 | } 40 | 41 | [Test] 42 | public void ShouldDrillDownThroughObjectLayers() 43 | { 44 | WhenTriggeringACompletion("StubType.StubTypeInstanceProperty.StubInstanceProperty."); 45 | TheCompletionList.ShouldContain(c => c.DisplayText == "ToLower"); 46 | } 47 | 48 | [Test] 49 | public void ShouldDrillDownThroughObjectMethods() 50 | { 51 | WhenTriggeringACompletion("StubType.StubTypeInstanceProperty.StubTypeInstanceProperty.StubInstanceProperty.ToLower()."); 52 | TheCompletionList.ShouldContain(c => c.DisplayText == "Split"); 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /src/SparkSense.Tests/TypeCompletion/WhenNavigatingThroughNameSpaces.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NUnit.Framework; 3 | using SparkSense.Tests.Scenarios; 4 | 5 | namespace SparkSense.Tests.TypeCompletion 6 | { 7 | public class WhenNavigatingThroughNameSpaces : TypeCompletionScenario 8 | { 9 | public WhenNavigatingThroughNameSpaces() 10 | { 11 | GivenReferencedTypes(new[] {typeof (StubType), typeof (String), typeof (Int32)}); 12 | } 13 | 14 | [Test] 15 | public void ShouldBeAbleToDigDownThroughNamespaceLayers() 16 | { 17 | WhenTriggeringACompletion("SparkSense."); 18 | TheCompletionList 19 | .ShouldNotContain(c => c.DisplayText == "System") 20 | .ShouldNotContain(c => c.DisplayText == "SparkSense") 21 | .ShouldContain(c => c.DisplayText == "Tests"); 22 | 23 | WhenTriggeringACompletion("SparkSense.Tests."); 24 | TheCompletionList 25 | .ShouldNotContain(c => c.DisplayText == "System") 26 | .ShouldNotContain(c => c.DisplayText == "SparkSense") 27 | .ShouldNotContain(c => c.DisplayText == "Tests") 28 | .ShouldContain(c => c.DisplayText == "Scenarios"); 29 | 30 | WhenTriggeringACompletion("SparkSense.Tests.Scenarios."); 31 | TheCompletionList 32 | .ShouldNotContain(c => c.DisplayText == "System") 33 | .ShouldNotContain(c => c.DisplayText == "SparkSense") 34 | .ShouldNotContain(c => c.DisplayText == "Tests") 35 | .ShouldNotContain(c => c.DisplayText == "Scenarios") 36 | .ShouldNotContain(c => c.DisplayText == string.Empty); 37 | } 38 | 39 | [Test] 40 | public void ShouldBeAbleToDigDownToTheActualTypeAtTheEndOfTheNamespace() 41 | { 42 | WhenTriggeringACompletion("System."); 43 | TheCompletionList.ShouldContain(c => c.DisplayText == "String"); 44 | TheCompletionList.ShouldContain(c => c.DisplayText == "Int32"); 45 | 46 | WhenTriggeringACompletion("SparkSense.Tests.Scenarios."); 47 | TheCompletionList.ShouldContain(c => c.DisplayText == "TypeResolutionScenario"); 48 | 49 | WhenTriggeringACompletion("SparkSense.Tests.Scenarios.TypeResolutionScenario."); 50 | TheCompletionList.ShouldContain(c => c.DisplayText == "StubType"); 51 | } 52 | 53 | [Test] 54 | public void ShouldBeAbleToStartFromPartialyThroughNamespaces() 55 | { 56 | WhenTriggeringACompletion("Tests."); 57 | TheCompletionList 58 | .ShouldNotContain(c => c.DisplayText == "System") 59 | .ShouldNotContain(c => c.DisplayText == "SparkSense") 60 | .ShouldNotContain(c => c.DisplayText == "Tests") 61 | .ShouldContain(c => c.DisplayText == "Scenarios"); 62 | 63 | WhenTriggeringACompletion("Tests.Scenarios."); 64 | TheCompletionList 65 | .ShouldNotContain(c => c.DisplayText == "System") 66 | .ShouldNotContain(c => c.DisplayText == "SparkSense") 67 | .ShouldNotContain(c => c.DisplayText == "Tests") 68 | .ShouldNotContain(c => c.DisplayText == "Scenarios") 69 | .ShouldNotContain(c => c.DisplayText == string.Empty); 70 | 71 | WhenTriggeringACompletion("Scenarios."); 72 | TheCompletionList 73 | .ShouldNotContain(c => c.DisplayText == "System") 74 | .ShouldNotContain(c => c.DisplayText == "SparkSense") 75 | .ShouldNotContain(c => c.DisplayText == "Tests") 76 | .ShouldNotContain(c => c.DisplayText == "Scenarios") 77 | .ShouldNotContain(c => c.DisplayText == string.Empty); 78 | } 79 | 80 | [Test] 81 | public void ShouldIncludeNameSpaceItemsInTheCompletionList() 82 | { 83 | WhenTriggeringAnInitialCompletion(); 84 | TheCompletionList.ShouldContain(c => c.DisplayText == "System"); 85 | TheCompletionList.ShouldContain(c => c.DisplayText == "SparkSense"); 86 | } 87 | 88 | [Test] 89 | public void ShouldNotIncludeAnyEmptyItemsInTheCompletionList() 90 | { 91 | WhenTriggeringACompletion("SparkSense.Tests.Scenarios."); 92 | TheCompletionList.ShouldNotContain(c => c.DisplayText == string.Empty); 93 | } 94 | 95 | [Test] 96 | public void ShouldNotIncludeTypesThemselvesInTheCompletionList() 97 | { 98 | WhenTriggeringACompletion("SparkSense."); 99 | TheCompletionList 100 | .ShouldNotContain(c => c.DisplayText == "StubType") 101 | .ShouldNotContain(c => c.DisplayText == "String") 102 | .ShouldNotContain(c => c.DisplayText == "Int32"); 103 | } 104 | } 105 | } -------------------------------------------------------------------------------- /src/SparkSense.Tests/TypeCompletion/WhenTriggeringTypeCompletion.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NUnit.Framework; 3 | using Spark; 4 | using SparkSense.Tests.Scenarios; 5 | 6 | namespace SparkSense.Tests.TypeCompletion 7 | { 8 | public class WhenTriggeringTypeCompletion : TypeCompletionScenario 9 | { 10 | public WhenTriggeringTypeCompletion() 11 | { 12 | GivenReferencedTypes(new[] {typeof (StubType), typeof(StubTypeWithNoStatics), typeof (String), typeof (Int32), typeof(SparkViewBase), typeof(AbstractSparkView)}); 13 | } 14 | 15 | [Test] 16 | public void ShouldIncludeTypesWithPublicMembersInTheCompletionList() 17 | { 18 | WhenTriggeringAnInitialCompletion(); 19 | TheCompletionList.ShouldNotContain(c => c.DisplayText == "StubPrivateType"); 20 | 21 | TheCompletionList.ShouldContain(c => c.DisplayText == "StubTypeWithNoStatics"); 22 | TheCompletionList.ShouldContain(c => c.DisplayText == "StubType"); 23 | TheCompletionList.ShouldContain(c => c.DisplayText == "String"); 24 | TheCompletionList.ShouldContain(c => c.DisplayText == "Int32"); 25 | } 26 | 27 | [Test] 28 | public void ShouldIncludeInitialNamespacesOfIncludedTypesInTheCompletionList() 29 | { 30 | WhenTriggeringAnInitialCompletion(); 31 | TheCompletionList.ShouldContain(c => c.DisplayText == "SparkSense"); 32 | TheCompletionList.ShouldContain(c => c.DisplayText == "System"); 33 | } 34 | 35 | [Test] 36 | public void ShouldNotContainDuplicatesInTheCompletionList() 37 | { 38 | WhenTriggeringAnInitialCompletion(); 39 | TheCompletionList.ShouldHaveCount(1, c => c.DisplayText == "System"); 40 | } 41 | 42 | [Test] 43 | public void ShouldContainStaticMembersInTheCompletionList() 44 | { 45 | WhenTriggeringACompletion("SparkSense.Tests.Scenarios.TypeResolutionScenario.StubType."); 46 | TheCompletionList.ShouldContain(c => c.DisplayText == "StubStaticField"); 47 | TheCompletionList.ShouldContain(c => c.DisplayText == "StubStaticMethod"); 48 | TheCompletionList.ShouldContain(c => c.DisplayText == "StubStaticProperty"); 49 | 50 | WhenTriggeringACompletion("Scenarios.TypeResolutionScenario.StubType."); 51 | TheCompletionList.ShouldContain(c => c.DisplayText == "StubStaticField"); 52 | TheCompletionList.ShouldContain(c => c.DisplayText == "StubStaticMethod"); 53 | TheCompletionList.ShouldContain(c => c.DisplayText == "StubStaticProperty"); 54 | 55 | WhenTriggeringACompletion("StubType."); 56 | TheCompletionList.ShouldContain(c => c.DisplayText == "StubStaticField"); 57 | TheCompletionList.ShouldContain(c => c.DisplayText == "StubStaticMethod"); 58 | TheCompletionList.ShouldContain(c => c.DisplayText == "StubStaticProperty"); 59 | } 60 | 61 | [Test] 62 | public void ShouldContainInstanceMembersOfSparkViewType() 63 | { 64 | WhenTriggeringAnInitialCompletion(); 65 | TheCompletionList 66 | .ShouldNotContain(c => c.DisplayText == "_sparkViewContext") 67 | .ShouldContain(c => c.DisplayText == "SparkViewContext"); 68 | 69 | TheCompletionList.ShouldContain(c => c.DisplayText == "OutputScope"); 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /src/SparkSense.Tests/TypeResolution/WhenResolvingInstanceMembers.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using NUnit.Framework; 3 | using SparkSense.Tests.Scenarios; 4 | 5 | namespace SparkSense.Tests.TypeResolution 6 | { 7 | public class WhenResolvingInstanceMembers : TypeResolutionScenario 8 | { 9 | public WhenResolvingInstanceMembers() 10 | { 11 | GivenReferencedTypes(new[] {typeof (StubType)}); 12 | WhenLookingUpInstanceMembers(); 13 | } 14 | 15 | [Test] 16 | public void ShouldFilterOutBackingAndStaticMembers() 17 | { 18 | TheResolvedMembers 19 | .ShouldNotContain(m => m.Name == "get_StubStaticProperty") 20 | .ShouldNotContain(m => m.Name == "StubStaticProperty") 21 | .ShouldNotContain(m => m.Name == "StubStaticMethod"); 22 | } 23 | 24 | [Test] 25 | public void ShouldResolvePublicInstanceField() 26 | { 27 | TheResolvedMembers 28 | .ShouldContain(m => m.Name == "StubInstanceField") 29 | .MemberType 30 | .ShouldBe(MemberTypes.Field); 31 | } 32 | 33 | [Test] 34 | public void ShouldResolvePublicInstanceMethod() 35 | { 36 | TheResolvedMembers 37 | .ShouldContain(m => m.Name == "StubInstanceMethod") 38 | .MemberType 39 | .ShouldBe(MemberTypes.Method); 40 | } 41 | 42 | [Test] 43 | public void ShouldResolvePublicInstanceProperty() 44 | { 45 | TheResolvedMembers 46 | .ShouldContain(m => m.Name == "StubInstanceProperty") 47 | .MemberType 48 | .ShouldBe(MemberTypes.Property); 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /src/SparkSense.Tests/TypeResolution/WhenResolvingMethods.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Reflection; 4 | using Fasterflect; 5 | using NUnit.Framework; 6 | using SparkSense.Tests.Scenarios; 7 | 8 | namespace SparkSense.Tests.TypeResolution 9 | { 10 | public class WhenResolvingMethods : TypeResolutionScenario 11 | { 12 | public WhenResolvingMethods() 13 | { 14 | GivenReferencedTypes(new[] {typeof (StubType)}); 15 | WhenLookingUpMethods("StubMethodWithParameters"); 16 | } 17 | 18 | [Test] 19 | public void ShouldResolveMethodParameters() 20 | { 21 | IList parameters = TheResolvedMethods 22 | .Where(m => m.Parameters().Count == 3).FirstOrDefault().Parameters(); 23 | 24 | parameters.ShouldHaveCount(3); 25 | parameters[0].Name.ShouldBe("param1"); 26 | parameters[0].ParameterType.Name.ShouldBe("String"); 27 | parameters[1].Name.ShouldBe("param2"); 28 | parameters[1].ParameterType.Name.ShouldBe("Int32"); 29 | parameters[2].Name.ShouldBe("param3"); 30 | parameters[2].ParameterType.Name.ShouldBe("StubType"); 31 | } 32 | 33 | [Test] 34 | public void ShouldResolveMultipleMethodsWithSameName() 35 | { 36 | TheResolvedMethods 37 | .ShouldHaveCount(3); 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /src/SparkSense.Tests/TypeResolution/WhenResolvingStaticMembers.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using NUnit.Framework; 3 | using SparkSense.Tests.Scenarios; 4 | 5 | namespace SparkSense.Tests.TypeResolution 6 | { 7 | public class WhenResolvingStaticMembers : TypeResolutionScenario 8 | { 9 | public WhenResolvingStaticMembers() 10 | { 11 | GivenReferencedTypes(new[] {typeof (StubType)}); 12 | WhenLookingUpStaticMembers(); 13 | } 14 | 15 | [Test] 16 | public void ShouldFilterOutBackingAndInstanceMembers() 17 | { 18 | TheResolvedMembers 19 | .ShouldNotContain(m => m.Name == "get_StubStaticProperty") 20 | .ShouldNotContain(m => m.Name == "StubInstanceProperty") 21 | .ShouldNotContain(m => m.Name == "StubInstanceMethod"); 22 | } 23 | 24 | [Test] 25 | public void ShouldResolvePublicStaticField() 26 | { 27 | TheResolvedMembers 28 | .ShouldContain(m => m.Name == "StubStaticField") 29 | .MemberType 30 | .ShouldBe(MemberTypes.Field); 31 | } 32 | 33 | [Test] 34 | public void ShouldResolvePublicStaticMethod() 35 | { 36 | TheResolvedMembers 37 | .ShouldContain(m => m.Name == "StubStaticMethod") 38 | .MemberType 39 | .ShouldBe(MemberTypes.Method); 40 | } 41 | 42 | [Test] 43 | public void ShouldResolvePublicStaticProperty() 44 | { 45 | TheResolvedMembers 46 | .ShouldContain(m => m.Name == "StubStaticProperty") 47 | .MemberType 48 | .ShouldBe(MemberTypes.Property); 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /src/SparkSense.Tests/TypeResolution/WhenResolvingTriggerTypes.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NUnit.Framework; 3 | using SparkSense.Tests.Scenarios; 4 | 5 | namespace SparkSense.Tests.TypeResolution 6 | { 7 | public class WhenResolvingTriggerTypes : TypeResolutionScenario 8 | { 9 | public WhenResolvingTriggerTypes() 10 | { 11 | GivenReferencedTypes(new[] { typeof(StubType), typeof(String), typeof(StubTypeWithNoStatics), typeof(StubPrivateType) }); 12 | WhenLookingUpTriggerTypes(); 13 | } 14 | 15 | [Test] 16 | public void ShouldOnlyResolveTypesThatArePublic() 17 | { 18 | TheResolvedTriggerTypes 19 | .ShouldHaveCount(3) 20 | .ShouldNotContain(t => t.Name == "StubPrivateType") 21 | .ShouldContain(t => t.Name == "StubType"); 22 | 23 | TheResolvedTriggerTypes 24 | .ShouldContain(t => t.Name == "StubTypeWithNoStatics"); 25 | 26 | TheResolvedTriggerTypes 27 | .ShouldContain(t => t.Name == "String"); 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /src/SparkSense.Tests/TypeResolution/WhenResolvingTypes.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NUnit.Framework; 3 | using Spark; 4 | using SparkSense.Tests.Scenarios; 5 | 6 | namespace SparkSense.Tests.TypeResolution 7 | { 8 | public class WhenResolvingTypes : TypeResolutionScenario 9 | { 10 | public WhenResolvingTypes() 11 | { 12 | GivenReferencedTypes(new[] { typeof(StubType), typeof(String), typeof(SparkViewBase), typeof(AbstractSparkView)}); 13 | } 14 | 15 | [Test] 16 | public void ShouldNotResolveTypeByNamespaceOnly() 17 | { 18 | WhenLookingUpSomeCode("SparkSense.Tests.Scenarios."); 19 | TheResolvedType 20 | .ShouldBe(null); 21 | TheRemainingCode 22 | .ShouldBe("SparkSense.Tests.Scenarios."); 23 | } 24 | 25 | [Test] 26 | public void ShouldTryResolveTypeByName() 27 | { 28 | WhenLookingUpSomeCode("StubType."); 29 | TheResolvedType 30 | .ShouldNotBeNull() 31 | .Name.ShouldBe("StubType"); 32 | TheRemainingCode 33 | .ShouldBe(string.Empty); 34 | } 35 | 36 | [Test] 37 | public void ShouldTryResolveTypeByFullName() 38 | { 39 | WhenLookingUpSomeCode("SparkSense.Tests.Scenarios.TypeResolutionScenario.StubType."); 40 | TheResolvedType 41 | .ShouldNotBeNull() 42 | .Name.ShouldBe("StubType"); 43 | TheRemainingCode 44 | .ShouldBe(string.Empty); 45 | } 46 | 47 | [Test] 48 | public void ShouldTryResolveTypeByPartialFullName() 49 | { 50 | WhenLookingUpSomeCode("Scenarios.TypeResolutionScenario.StubType."); 51 | TheResolvedType 52 | .ShouldNotBeNull() 53 | .Name.ShouldBe("StubType"); 54 | TheRemainingCode 55 | .ShouldBe(string.Empty); 56 | } 57 | 58 | [Test] 59 | public void ShouldTryResolveTypeByNameAndMember() 60 | { 61 | WhenLookingUpSomeCode("StubType.StubInstanceProperty."); 62 | TheResolvedType 63 | .ShouldNotBeNull() 64 | .Name.ShouldBe("StubType"); 65 | TheRemainingCode 66 | .ShouldBe("StubInstanceProperty"); 67 | 68 | WhenLookingUpSomeCode("String.ToLower("); 69 | TheResolvedType 70 | .ShouldNotBeNull() 71 | .Name.ShouldBe("String"); 72 | TheRemainingCode 73 | .ShouldBe("ToLower("); 74 | 75 | WhenLookingUpSomeCode("String.ToLower().ToUpper("); 76 | TheResolvedType 77 | .ShouldNotBeNull() 78 | .Name.ShouldBe("String"); 79 | TheRemainingCode 80 | .ShouldBe("ToLower().ToUpper("); 81 | } 82 | 83 | [Test] 84 | public void ShouldTryResolveTypeByKeyword() 85 | { 86 | WhenLookingUpSomeCode("this."); 87 | TheResolvedType 88 | .ShouldNotBeNull() 89 | .Name.ShouldBe("AbstractSparkView"); 90 | TheRemainingCode 91 | .ShouldBe(string.Empty); 92 | 93 | WhenLookingUpSomeCode("this.OutputScope("); 94 | TheResolvedType 95 | .ShouldNotBeNull() 96 | .Name.ShouldBe("AbstractSparkView"); 97 | TheRemainingCode 98 | .ShouldBe("OutputScope("); 99 | } 100 | } 101 | } -------------------------------------------------------------------------------- /src/SparkSense.Tests/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/SparkSense.gpState: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /src/SparkSense.ncrunchsolution: -------------------------------------------------------------------------------- 1 | 2 | 0 3 | Default 4 | false 5 | UseDynamicAnalysis 6 | UseStaticAnalysis 7 | UseStaticAnalysis 8 | UseStaticAnalysis 9 | Run all tests automatically:BFRydWU=;Run all tests manually:BUZhbHNl;Run impacted tests automatically, others manually (experimental!):CklzSW1wYWN0ZWQ=;Run pinned tests automatically, others manually:CElzUGlubmVk 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/SparkSense.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SparkSense", "SparkSense\SparkSense.csproj", "{6E9BC746-755B-460E-8556-A73985E32BAE}" 5 | EndProject 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SparkSense.Tests", "SparkSense.Tests\SparkSense.Tests.csproj", "{89182868-234D-465D-ABFD-CD873E233547}" 7 | EndProject 8 | 9 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{1CDD2B30-0999-48D7-B8A4-9AF23ECE81DB}" 10 | ProjectSection(SolutionItems) = preProject 11 | .nuget\NuGet.Config = .nuget\NuGet.Config 12 | .nuget\NuGet.exe = .nuget\NuGet.exe 13 | .nuget\NuGet.targets = .nuget\NuGet.targets 14 | EndProjectSection 15 | EndProject 16 | 17 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ItemTemplates", "ItemTemplates", "{E6B032ED-07C1-46B2-8AB0-A19C3F3E15E1}" 18 | EndProject 19 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ViewPage", "ItemTemplates\ViewPage\ViewPage.csproj", "{977A1109-A90E-40DE-B976-04A406B9114D}" 20 | EndProject 21 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LayoutPage", "ItemTemplates\LayoutPage\LayoutPage.csproj", "{080A3968-BA97-48B2-AC8C-19AC327E62C6}" 22 | EndProject 23 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ViewPageWithLayout", "ItemTemplates\ViewPageWithLayout\ViewPageWithLayout.csproj", "{24C1E236-C53F-47E8-AA1B-68FE5264C934}" 24 | EndProject 25 | Global 26 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 27 | Debug|Any CPU = Debug|Any CPU 28 | Debug|x86 = Debug|x86 29 | Release|Any CPU = Release|Any CPU 30 | Release|x86 = Release|x86 31 | Retail|Any CPU = Retail|Any CPU 32 | Retail|x86 = Retail|x86 33 | EndGlobalSection 34 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 35 | {6E9BC746-755B-460E-8556-A73985E32BAE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 36 | {6E9BC746-755B-460E-8556-A73985E32BAE}.Debug|Any CPU.Build.0 = Debug|Any CPU 37 | {6E9BC746-755B-460E-8556-A73985E32BAE}.Debug|x86.ActiveCfg = Debug|x86 38 | {6E9BC746-755B-460E-8556-A73985E32BAE}.Debug|x86.Build.0 = Debug|x86 39 | {6E9BC746-755B-460E-8556-A73985E32BAE}.Release|Any CPU.ActiveCfg = Release|Any CPU 40 | {6E9BC746-755B-460E-8556-A73985E32BAE}.Release|Any CPU.Build.0 = Release|Any CPU 41 | {6E9BC746-755B-460E-8556-A73985E32BAE}.Release|x86.ActiveCfg = Release|x86 42 | {6E9BC746-755B-460E-8556-A73985E32BAE}.Release|x86.Build.0 = Release|x86 43 | {6E9BC746-755B-460E-8556-A73985E32BAE}.Retail|Any CPU.ActiveCfg = Release|x86 44 | {6E9BC746-755B-460E-8556-A73985E32BAE}.Retail|x86.ActiveCfg = Release|x86 45 | {6E9BC746-755B-460E-8556-A73985E32BAE}.Retail|x86.Build.0 = Release|x86 46 | {89182868-234D-465D-ABFD-CD873E233547}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 47 | {89182868-234D-465D-ABFD-CD873E233547}.Debug|Any CPU.Build.0 = Debug|Any CPU 48 | {89182868-234D-465D-ABFD-CD873E233547}.Debug|x86.ActiveCfg = Debug|x86 49 | {89182868-234D-465D-ABFD-CD873E233547}.Debug|x86.Build.0 = Debug|x86 50 | {89182868-234D-465D-ABFD-CD873E233547}.Release|Any CPU.ActiveCfg = Release|Any CPU 51 | {89182868-234D-465D-ABFD-CD873E233547}.Release|Any CPU.Build.0 = Release|Any CPU 52 | {89182868-234D-465D-ABFD-CD873E233547}.Release|x86.ActiveCfg = Release|x86 53 | {89182868-234D-465D-ABFD-CD873E233547}.Release|x86.Build.0 = Release|x86 54 | {89182868-234D-465D-ABFD-CD873E233547}.Retail|Any CPU.ActiveCfg = Release|x86 55 | {89182868-234D-465D-ABFD-CD873E233547}.Retail|x86.ActiveCfg = Release|x86 56 | {89182868-234D-465D-ABFD-CD873E233547}.Retail|x86.Build.0 = Release|x86 57 | {977A1109-A90E-40DE-B976-04A406B9114D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 58 | {977A1109-A90E-40DE-B976-04A406B9114D}.Debug|Any CPU.Build.0 = Debug|Any CPU 59 | {977A1109-A90E-40DE-B976-04A406B9114D}.Debug|x86.ActiveCfg = Debug|Any CPU 60 | {977A1109-A90E-40DE-B976-04A406B9114D}.Release|Any CPU.ActiveCfg = Release|Any CPU 61 | {977A1109-A90E-40DE-B976-04A406B9114D}.Release|Any CPU.Build.0 = Release|Any CPU 62 | {977A1109-A90E-40DE-B976-04A406B9114D}.Release|x86.ActiveCfg = Release|Any CPU 63 | {977A1109-A90E-40DE-B976-04A406B9114D}.Retail|Any CPU.ActiveCfg = Release|Any CPU 64 | {977A1109-A90E-40DE-B976-04A406B9114D}.Retail|Any CPU.Build.0 = Release|Any CPU 65 | {977A1109-A90E-40DE-B976-04A406B9114D}.Retail|x86.ActiveCfg = Release|Any CPU 66 | {080A3968-BA97-48B2-AC8C-19AC327E62C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 67 | {080A3968-BA97-48B2-AC8C-19AC327E62C6}.Debug|Any CPU.Build.0 = Debug|Any CPU 68 | {080A3968-BA97-48B2-AC8C-19AC327E62C6}.Debug|x86.ActiveCfg = Debug|Any CPU 69 | {080A3968-BA97-48B2-AC8C-19AC327E62C6}.Release|Any CPU.ActiveCfg = Release|Any CPU 70 | {080A3968-BA97-48B2-AC8C-19AC327E62C6}.Release|Any CPU.Build.0 = Release|Any CPU 71 | {080A3968-BA97-48B2-AC8C-19AC327E62C6}.Release|x86.ActiveCfg = Release|Any CPU 72 | {080A3968-BA97-48B2-AC8C-19AC327E62C6}.Retail|Any CPU.ActiveCfg = Release|Any CPU 73 | {080A3968-BA97-48B2-AC8C-19AC327E62C6}.Retail|Any CPU.Build.0 = Release|Any CPU 74 | {080A3968-BA97-48B2-AC8C-19AC327E62C6}.Retail|x86.ActiveCfg = Release|Any CPU 75 | {24C1E236-C53F-47E8-AA1B-68FE5264C934}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 76 | {24C1E236-C53F-47E8-AA1B-68FE5264C934}.Debug|Any CPU.Build.0 = Debug|Any CPU 77 | {24C1E236-C53F-47E8-AA1B-68FE5264C934}.Debug|x86.ActiveCfg = Debug|Any CPU 78 | {24C1E236-C53F-47E8-AA1B-68FE5264C934}.Release|Any CPU.ActiveCfg = Release|Any CPU 79 | {24C1E236-C53F-47E8-AA1B-68FE5264C934}.Release|Any CPU.Build.0 = Release|Any CPU 80 | {24C1E236-C53F-47E8-AA1B-68FE5264C934}.Release|x86.ActiveCfg = Release|Any CPU 81 | {24C1E236-C53F-47E8-AA1B-68FE5264C934}.Retail|Any CPU.ActiveCfg = Release|Any CPU 82 | {24C1E236-C53F-47E8-AA1B-68FE5264C934}.Retail|Any CPU.Build.0 = Release|Any CPU 83 | {24C1E236-C53F-47E8-AA1B-68FE5264C934}.Retail|x86.ActiveCfg = Release|Any CPU 84 | EndGlobalSection 85 | GlobalSection(SolutionProperties) = preSolution 86 | HideSolutionNode = FALSE 87 | EndGlobalSection 88 | GlobalSection(NestedProjects) = preSolution 89 | {977A1109-A90E-40DE-B976-04A406B9114D} = {E6B032ED-07C1-46B2-8AB0-A19C3F3E15E1} 90 | {080A3968-BA97-48B2-AC8C-19AC327E62C6} = {E6B032ED-07C1-46B2-8AB0-A19C3F3E15E1} 91 | {24C1E236-C53F-47E8-AA1B-68FE5264C934} = {E6B032ED-07C1-46B2-8AB0-A19C3F3E15E1} 92 | EndGlobalSection 93 | EndGlobal 94 | -------------------------------------------------------------------------------- /src/SparkSense/ContentType/SparkFileAndContentTypes.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.Composition; 2 | using Microsoft.VisualStudio.Utilities; 3 | 4 | namespace SparkSense.ContentType 5 | { 6 | internal static class SparkFileAndContentTypes 7 | { 8 | [Export] 9 | [Name("spark")] 10 | [DisplayName("Spark")] 11 | [BaseDefinition("HTML")] 12 | internal static ContentTypeDefinition SparkContentTypeDefinition = null; 13 | 14 | [Export] 15 | [FileExtension(".spark")] 16 | [ContentType("spark")] 17 | internal static FileExtensionToContentTypeDefinition SparkFileExtensionDefinition = null; 18 | } 19 | } -------------------------------------------------------------------------------- /src/SparkSense/Parser/CompletionBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | using Fasterflect; 6 | using Microsoft.VisualStudio.Language.Intellisense; 7 | using Spark.Compiler; 8 | using SparkSense.Parsing; 9 | 10 | namespace SparkSense.Parser 11 | { 12 | public class CompletionBuilder 13 | { 14 | private readonly TypeNavigator _typeNavigator; 15 | private readonly IViewExplorer _viewExplorer; 16 | 17 | public CompletionBuilder(IViewExplorer viewExplorer) 18 | { 19 | if (viewExplorer == null) throw new ArgumentNullException("viewExplorer"); 20 | _viewExplorer = viewExplorer; 21 | _typeNavigator = viewExplorer.GetTypeNavigator(); 22 | } 23 | 24 | public IEnumerable ToCompletionList(string codeSnippit) 25 | { 26 | Type resolvedType; 27 | string remainingCode; 28 | if (_typeNavigator.TryResolveType(_viewExplorer, codeSnippit, out resolvedType, out remainingCode)) 29 | { 30 | if (string.IsNullOrEmpty(remainingCode)) 31 | return ResolveTypeMemberCompletions(resolvedType); 32 | return ResolveInstanceMemberCompletions(resolvedType, remainingCode); 33 | } 34 | 35 | IEnumerable namespaceElements = 36 | _typeNavigator.Types.Select(t => _typeNavigator.GetMatchingNamespaceElements(t, codeSnippit)); 37 | IEnumerable viewDataElements = _viewExplorer.GetViewDataVariableChunks(); 38 | IEnumerable viewLocalElements = _viewExplorer.GetLocalVariableChunks(); 39 | if (string.IsNullOrEmpty(codeSnippit)) 40 | { 41 | IEnumerable triggerTypes = _typeNavigator.GetTriggerTypes(); 42 | IEnumerable viewMembers = _typeNavigator.GetViewInstanceMembers(triggerTypes); 43 | return triggerTypes 44 | .Union(viewMembers).ToCompletionList() 45 | .Union(namespaceElements.ToCompletionList()) 46 | .Union(viewDataElements.ToCompletionList()) 47 | .Union(viewLocalElements.ToCompletionList()); 48 | } 49 | return namespaceElements.ToCompletionList(); 50 | } 51 | 52 | private IEnumerable ResolveInstanceMemberCompletions(Type resolvedType, string remainingCode) 53 | { 54 | if (remainingCode.EndsWith("(")) return null; 55 | string[] fragments = remainingCode.Split(new[] {".", "(", ")"}, StringSplitOptions.RemoveEmptyEntries); 56 | var flags = Flags.Instance | Flags.Static; 57 | MemberInfo resolvedMember = _typeNavigator.GetResolvedMember(resolvedType, fragments.First(), flags); 58 | 59 | IEnumerable remainingFragments = fragments.Skip(1); 60 | while (resolvedMember != null) 61 | { 62 | resolvedType = _typeNavigator.GetResolvedType(resolvedMember) ?? resolvedType; 63 | resolvedMember = _typeNavigator.GetResolvedMember(resolvedType, remainingFragments.FirstOrDefault(), flags); 64 | remainingFragments = remainingFragments.Skip(1); 65 | } 66 | 67 | IEnumerable instanceMembers = _typeNavigator.GetMembers(resolvedType, flags); 68 | return instanceMembers.ToCompletionList(); 69 | } 70 | 71 | private IEnumerable ResolveTypeMemberCompletions(Type resolvedType) 72 | { 73 | IEnumerable members = _typeNavigator.GetMembers(resolvedType, Flags.Static | Flags.Instance); 74 | IEnumerable memberCompletions = members.ToCompletionList(); 75 | return memberCompletions; 76 | } 77 | } 78 | } -------------------------------------------------------------------------------- /src/SparkSense/Parser/CompletionGrammar.cs: -------------------------------------------------------------------------------- 1 | using Spark.Parser; 2 | using Spark.Parser.Markup; 3 | 4 | namespace SparkSense.Parser 5 | { 6 | public class CompletionGrammar : MarkupGrammar 7 | { 8 | public ParseAction IncompleteCode; 9 | 10 | public CompletionGrammar() : base(new ParserSettings()) 11 | { 12 | IncompleteCode = TkCode(Ch("${").Or(Ch("!{"))).And(Text) 13 | .Build(hit => new ExpressionNode(hit.Down.Text)); 14 | 15 | var LessThanTextNode = Ch('<').Build(hit => (Node) new TextNode("<")); 16 | 17 | var EntityRefOrAmpersand = AsNode(EntityRef).Or(Ch('&').Build(hit => (Node)new TextNode("&"))); 18 | 19 | AnyNode = 20 | 21 | AsNode(Element).Paint() 22 | .Or(AsNode(EndElement).Paint()) 23 | .Or(EntityRefOrAmpersand.Paint()) 24 | .Or(AsNode(Statement)) 25 | .Or(AsNode(Code).Paint()) 26 | .Or(AsNode(IncompleteCode).Paint()) 27 | .Or(AsNode(Text).Paint()) 28 | .Or(AsNode(DoctypeDecl).Paint()) 29 | .Or(AsNode(Comment).Paint()) 30 | .Or(AsNode(XMLDecl).Paint()) 31 | .Or(AsNode(ProcessingInstruction).Paint()) 32 | .Or(AsNode(LessThanTextNode).Paint()); 33 | 34 | Nodes = Rep(AnyNode); 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /src/SparkSense/Parser/CompletionSyntaxProvider.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Spark.Compiler; 3 | using Spark.Compiler.NodeVisitors; 4 | using Spark.Parser; 5 | using Spark.Parser.Markup; 6 | using Spark.Parser.Syntax; 7 | 8 | namespace SparkSense.Parser 9 | { 10 | public class CompletionSyntaxProvider : DefaultSyntaxProvider 11 | { 12 | private readonly CompletionGrammar _grammar; 13 | 14 | public CompletionSyntaxProvider() : base(new ParserSettings()) 15 | { 16 | _grammar = new CompletionGrammar(); 17 | } 18 | 19 | public override IList GetChunks(VisitorContext context, string path) 20 | { 21 | context.SyntaxProvider = this; 22 | context.ViewPath = path; 23 | 24 | SourceContext sourceContext = CreateSourceContext(context.ViewPath, context.ViewFolder); 25 | var position = new Position(sourceContext); 26 | 27 | ParseResult> result = _grammar.Nodes(position); 28 | if (result.Rest.PotentialLength() != 0) 29 | { 30 | ThrowParseException(context.ViewPath, position, result.Rest); 31 | } 32 | 33 | context.Paint = result.Rest.GetPaint(); 34 | 35 | IList nodes = result.Value; 36 | foreach (INodeVisitor visitor in BuildNodeVisitors(context)) 37 | { 38 | visitor.Accept(nodes); 39 | nodes = visitor.Nodes; 40 | } 41 | 42 | var chunkBuilder = new ChunkBuilderVisitor(context); 43 | chunkBuilder.Accept(nodes); 44 | return chunkBuilder.Chunks; 45 | } 46 | 47 | private IList BuildNodeVisitors(VisitorContext context) 48 | { 49 | return new INodeVisitor[] 50 | { 51 | new NamespaceVisitor(context), 52 | new IncludeVisitor(context), 53 | new PrefixExpandingVisitor(context), 54 | new SpecialNodeVisitor(context), 55 | new CacheAttributeVisitor(context), 56 | new WhitespaceCleanerVisitor(context), 57 | new ForEachAttributeVisitor(context), 58 | new ConditionalAttributeVisitor(context), 59 | new TestElseElementVisitor(context), 60 | new OnceAttributeVisitor(context), 61 | new UrlAttributeVisitor(context), 62 | new BindingExpansionVisitor(context) 63 | }; 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /src/SparkSense/Parsing/CachingViewFolder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Spark.FileSystem; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | 6 | namespace SparkSense.Parsing 7 | { 8 | public class CachingViewFolder : IViewFolder 9 | { 10 | private FileSystemViewFolder _disk; 11 | private InMemoryViewFolder _cache; 12 | 13 | public CachingViewFolder(string basePath) 14 | { 15 | _cache = new InMemoryViewFolder(); 16 | _disk = new FileSystemViewFolder(basePath); 17 | BasePath = basePath; 18 | } 19 | 20 | public string BasePath { get; private set; } 21 | 22 | public IViewFile GetViewSource(string path) 23 | { 24 | if (!_cache.HasView(path) || _cache[path].Length == 0) 25 | { 26 | LoadFromDisk(path); 27 | } 28 | return _cache.GetViewSource(path); 29 | } 30 | 31 | public void SetViewSource(string path, string content) 32 | { 33 | _cache.Set(path, content); 34 | } 35 | 36 | public IList ListViews(string path) 37 | { 38 | return _disk.ListViews(path); 39 | } 40 | 41 | public bool HasView(string path) 42 | { 43 | return _cache.HasView(path) || _disk.HasView(path); 44 | } 45 | 46 | public void Add(string path) 47 | { 48 | if(!_cache.ContainsKey(path)) 49 | _cache.Add(path, null); 50 | } 51 | 52 | private void LoadFromDisk(string path) 53 | { 54 | var fileContents = _disk.GetViewSource(path); 55 | string contents; 56 | using (TextReader reader = new StreamReader(fileContents.OpenViewStream())) 57 | contents = reader.ReadToEnd(); 58 | _cache.Set(path, contents); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/SparkSense/Parsing/Constants.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace SparkSense.Parsing 3 | { 4 | public static class Constants 5 | { 6 | public const char COLON = ':'; 7 | public const char OPEN_ELEMENT = '<'; 8 | public const char SPACE = ' '; 9 | public const char EQUALS = '='; 10 | public const char DOUBLE_QUOTE = '"'; 11 | public const char SINGLE_QUOTE = '\''; 12 | public const char OPEN_BRACE = '{'; 13 | public const char CLOSE_ELEMENT = '>'; 14 | public const char CLOSE_BRACE = '}'; 15 | public const char FWD_SLASH = '/'; 16 | public const char EXCLAMATION = '!'; 17 | public const char DOLLAR = '$'; 18 | public const char PERIOD = '.'; 19 | public const string SELF_CLOSE_ELEMENT = "/>"; 20 | 21 | public const string ICON_SparkElement = "SparkElement"; 22 | public const string ICON_SparkPartial = "SparkPartial"; 23 | public const string ICON_SparkPartialParameter = "SparkPartialParameter"; 24 | public const string ICON_SparkAttribute = "SparkAttribute"; 25 | public const string ICON_SparkContentName = "SparkContentName"; 26 | public const string ICON_SparkGlobalVariable = "SparkGlobalVariable"; 27 | public const string ICON_SparkLocalVariable = "SparkLocalVariable"; 28 | public const string ICON_SparkMacro = "SparkMacro"; 29 | public const string ICON_SparkMacroParameter = "SparkMacroParameter"; 30 | 31 | public const string ICON_Property = "Property"; 32 | public const string ICON_Method = "Method"; 33 | public const string ICON_Field = "Field"; 34 | public const string ICON_Class = "Class"; 35 | public const string ICON_Event = "Event"; 36 | public const string ICON_Namespace = "Namespace"; 37 | 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/SparkSense/Parsing/IProjectExplorer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Spark.FileSystem; 4 | using Microsoft.VisualStudio.Text; 5 | 6 | namespace SparkSense.Parsing 7 | { 8 | public interface IProjectExplorer 9 | { 10 | bool ViewFolderExists(); 11 | IViewFolder GetViewFolder(); 12 | IViewExplorer GetViewExplorer(ITextBuffer textBuffer); 13 | string GetCurrentViewPath(ITextBuffer textBuffer); 14 | void SetViewContent(string viewPath, string content); 15 | IEnumerable GetProjectReferencedTypes(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/SparkSense/Parsing/IViewExplorer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Spark.Compiler; 4 | 5 | namespace SparkSense.Parsing 6 | { 7 | public interface IViewExplorer 8 | { 9 | IList GetRelatedPartials(); 10 | IList GetPossibleMasterLayouts(); 11 | IList GetPossiblePartialDefaults(string partialName); 12 | IList GetGlobalVariables(); 13 | IList GetLocalVariables(); 14 | IList GetContentNames(); 15 | IList GetLocalMacros(); 16 | IList GetMacroParameters(string macroName); 17 | IList GetMembers(); 18 | void InvalidateView(string newContent); 19 | TypeNavigator GetTypeNavigator(); 20 | IEnumerable GetLocalVariableChunks(); 21 | IEnumerable GetViewDataVariableChunks(); 22 | IEnumerable GetAssignedVariableChunks(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/SparkSense/Parsing/ParsingExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System; 3 | 4 | namespace SparkSense.Parsing 5 | { 6 | public static class ParsingExtensions 7 | { 8 | public static bool IsNonPartialSparkFile(this string filePath) 9 | { 10 | return filePath.EndsWith(".spark") && !Path.GetFileName(filePath).StartsWith("_"); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/SparkSense/Parsing/ProjectExplorer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.Design; 4 | using System.IO; 5 | using EnvDTE; 6 | using Microsoft.VisualStudio.Shell.Design; 7 | using Microsoft.VisualStudio.Shell.Interop; 8 | using Microsoft.VisualStudio.Text; 9 | using Spark.FileSystem; 10 | 11 | namespace SparkSense.Parsing 12 | { 13 | public class ProjectExplorer : IProjectExplorer 14 | { 15 | private readonly ISparkServiceProvider _services; 16 | private ITypeDiscoveryService _discovery; 17 | private IVsHierarchy _hier; 18 | private IEnumerable _projectReferencedTypes; 19 | private CachingViewFolder _projectViewFolder; 20 | 21 | public ProjectExplorer(ISparkServiceProvider services) 22 | { 23 | if (services == null) throw new ArgumentNullException("services", "services is null."); 24 | _services = services; 25 | InitTypes(); 26 | } 27 | 28 | private void InitTypes() 29 | { 30 | InitTypeDiscoveryService(); 31 | GetProjectReferencedTypes(); 32 | } 33 | 34 | private CachingViewFolder ProjectViewFolder 35 | { 36 | get 37 | { 38 | string activeDocumentPath; 39 | if (!TryGetActiveDocumentPath(out activeDocumentPath)) return null; 40 | 41 | if (_projectViewFolder == null || _projectViewFolder.BasePath != GetViewRoot(activeDocumentPath)) 42 | { 43 | _hier = null; 44 | _discovery = null; 45 | _projectReferencedTypes = null; 46 | _projectViewFolder = new CachingViewFolder(GetViewRoot(activeDocumentPath) ?? string.Empty); 47 | InitTypes(); 48 | BuildViewMapFromProjectEnvironment(); 49 | } 50 | return _projectViewFolder; 51 | } 52 | } 53 | 54 | #region IProjectExplorer Members 55 | 56 | public bool ViewFolderExists() 57 | { 58 | string activeDocumentPath; 59 | if (!TryGetActiveDocumentPath(out activeDocumentPath)) return false; 60 | 61 | int viewsLocationStart = activeDocumentPath.LastIndexOf("Views"); 62 | return viewsLocationStart != -1; 63 | } 64 | 65 | public IViewFolder GetViewFolder() 66 | { 67 | string activeDocumentPath; 68 | if (!TryGetActiveDocumentPath(out activeDocumentPath)) return null; 69 | 70 | return ProjectViewFolder; 71 | } 72 | 73 | public IViewExplorer GetViewExplorer(ITextBuffer textBuffer) 74 | { 75 | IViewExplorer viewExplorer; 76 | if (textBuffer.Properties.TryGetProperty(typeof (ViewExplorer), out viewExplorer)) 77 | return viewExplorer; 78 | 79 | viewExplorer = new ViewExplorer(this, GetCurrentViewPath(textBuffer)); 80 | textBuffer.Properties.AddProperty(typeof (ViewExplorer), viewExplorer); 81 | return viewExplorer; 82 | } 83 | 84 | public string GetCurrentViewPath(ITextBuffer textBuffer) 85 | { 86 | var adapter = _services.AdaptersFactoryService.GetBufferAdapter(textBuffer) as IPersistFileFormat; 87 | if (adapter == null) return string.Empty; 88 | 89 | string filename; 90 | uint format; 91 | adapter.GetCurFile(out filename, out format); 92 | return GetViewPath(filename); 93 | } 94 | 95 | public void SetViewContent(string viewPath, string content) 96 | { 97 | ProjectViewFolder.SetViewSource(viewPath, content); 98 | } 99 | 100 | public IEnumerable GetProjectReferencedTypes() 101 | { 102 | if (_projectReferencedTypes != null) return _projectReferencedTypes; 103 | try 104 | { 105 | _projectReferencedTypes = _discovery.GetTypes(typeof (object), true) as IEnumerable; 106 | } 107 | catch (NullReferenceException) 108 | { 109 | //Type Discovery service isn't ready yet. 110 | } 111 | catch (Exception) 112 | { 113 | throw; 114 | } 115 | return _projectReferencedTypes; 116 | } 117 | 118 | #endregion 119 | 120 | public string GetCurrentViewPath() 121 | { 122 | string activeDocumentPath; 123 | if (!TryGetActiveDocumentPath(out activeDocumentPath)) return null; 124 | return GetViewPath(activeDocumentPath); 125 | } 126 | 127 | public bool HasView(string viewPath) 128 | { 129 | return ProjectViewFolder.HasView(viewPath); 130 | } 131 | 132 | private bool TryGetActiveDocumentPath(out string activeDocumentPath) 133 | { 134 | activeDocumentPath = _services.VsEnvironment.ActiveDocument != null 135 | ? _services.VsEnvironment.ActiveDocument.FullName 136 | : string.Empty; 137 | return !String.IsNullOrEmpty(activeDocumentPath); 138 | } 139 | 140 | private void BuildViewMapFromProjectEnvironment() 141 | { 142 | if (_services.VsEnvironment.ActiveDocument == null) return; 143 | Project currentProject = _services.VsEnvironment.ActiveDocument.ProjectItem.ContainingProject; 144 | foreach (ProjectItem projectItem in currentProject.ProjectItems) 145 | ScanProjectItemForViews(projectItem); 146 | } 147 | 148 | private void ScanProjectItemForViews(ProjectItem projectItem) 149 | { 150 | if (projectItem.Name.EndsWith(".spark")) 151 | { 152 | string projectItemMap = GetProjectItemMap(projectItem); 153 | if (!string.IsNullOrEmpty(projectItemMap)) 154 | ProjectViewFolder.Add(projectItemMap); 155 | } 156 | 157 | if (projectItem.ProjectItems != null) 158 | foreach (ProjectItem child in projectItem.ProjectItems) 159 | ScanProjectItemForViews(child); 160 | } 161 | 162 | private string GetProjectItemMap(ProjectItem projectItem) 163 | { 164 | if (projectItem.Properties == null) return null; 165 | 166 | string fullPath = projectItem.Properties.Item("FullPath").Value.ToString(); 167 | 168 | var foundView = GetViewPath(fullPath); 169 | 170 | return foundView; 171 | } 172 | 173 | private string GetViewPath(string fullPath) { 174 | string viewRoot = GetViewRoot(fullPath); 175 | if(string.IsNullOrEmpty(viewRoot)) 176 | return fullPath; 177 | return fullPath.Replace(viewRoot, string.Empty).TrimStart('\\'); 178 | } 179 | 180 | private string GetViewRoot(string activeDocumentPath) 181 | { 182 | int viewsLocationStart = activeDocumentPath.LastIndexOf("Views"); 183 | return viewsLocationStart != -1 ? activeDocumentPath.Substring(0, viewsLocationStart + 5) : GetProjectRoot(); 184 | } 185 | 186 | private string GetProjectRoot() 187 | { 188 | var projectFileName = _services.VsEnvironment.ActiveDocument.ProjectItem.ContainingProject.FullName; 189 | return Path.GetDirectoryName(projectFileName); 190 | } 191 | 192 | private IVsHierarchy GetHierarchy() 193 | { 194 | if (_hier == null) 195 | { 196 | var sln = _services.GetService(); 197 | if (_services.VsEnvironment.ActiveDocument != null) 198 | { 199 | string projectName = _services.VsEnvironment.ActiveDocument.ProjectItem.ContainingProject.UniqueName; 200 | sln.GetProjectOfUniqueName(projectName, out _hier); 201 | } 202 | } 203 | return _hier; 204 | } 205 | 206 | private void InitTypeDiscoveryService() 207 | { 208 | if (_discovery != null) return; 209 | DynamicTypeService typeService = _services.TypeService; 210 | if (typeService != null) 211 | _discovery = typeService.GetTypeDiscoveryService(GetHierarchy()); 212 | } 213 | } 214 | } -------------------------------------------------------------------------------- /src/SparkSense/Parsing/ViewExplorer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Spark.Compiler; 5 | using Spark.Parser; 6 | using Spark.Parser.Syntax; 7 | using System.IO; 8 | using System; 9 | using Spark; 10 | using System.Diagnostics; 11 | using System.Reflection; 12 | using SparkSense.Parser; 13 | 14 | namespace SparkSense.Parsing 15 | { 16 | public class ViewExplorer : IViewExplorer 17 | { 18 | private IProjectExplorer _projectExplorer; 19 | private ViewLoader _viewLoader; 20 | private readonly string _viewPath; 21 | private TypeNavigator _typeNavigator; 22 | 23 | public ViewExplorer(IProjectExplorer projectExplorer, string viewPath) 24 | { 25 | if (projectExplorer == null) 26 | throw new ArgumentNullException("projectExplorer", "Project Explorer is null. We need a hook into the VS Environment"); 27 | 28 | _projectExplorer = projectExplorer; 29 | _viewPath = viewPath; 30 | _viewLoader = new ViewLoader 31 | { 32 | ViewFolder = _projectExplorer.GetViewFolder(), 33 | SyntaxProvider = new CompletionSyntaxProvider() 34 | }; 35 | InitViewChunks(); 36 | } 37 | 38 | public IList GetRelatedPartials() 39 | { 40 | return _viewLoader.FindPartialFiles(_viewPath); 41 | } 42 | 43 | public IList GetGlobalVariables() 44 | { 45 | var globalVariables = new List(); 46 | 47 | GetAllChunks() 48 | .ToList() 49 | .ForEach(globalVar => globalVariables.Add(globalVar.Name)); 50 | 51 | return globalVariables; 52 | } 53 | 54 | public IList GetLocalVariables() 55 | { 56 | var allLocalVariables = new List(); 57 | var locals = GetLocalVariableChunks(); 58 | var assigned = GetAssignedVariableChunks(); 59 | var viewData = GetViewDataVariableChunks(); 60 | 61 | locals.ToList().ForEach(x => allLocalVariables.Add(x.Name)); 62 | assigned.ToList().ForEach(x => allLocalVariables.Add(x.Name)); 63 | viewData.ToList().ForEach(x => allLocalVariables.Add(x.Name)); 64 | 65 | return allLocalVariables; 66 | } 67 | 68 | public IEnumerable GetViewDataVariableChunks() 69 | { 70 | return GetViewChunks(); 71 | } 72 | 73 | public IEnumerable GetAssignedVariableChunks() 74 | { 75 | return GetViewChunks(); 76 | } 77 | 78 | public IEnumerable GetLocalVariableChunks() 79 | { 80 | return GetViewChunks(); 81 | } 82 | 83 | public IList GetPossibleMasterLayouts() 84 | { 85 | var possibleMasters = new List(); 86 | possibleMasters.AddRange(GetPossibleMasterFiles("Layouts")); 87 | possibleMasters.AddRange(GetPossibleMasterFiles("Shared")); 88 | return possibleMasters; 89 | } 90 | 91 | public IList GetPossiblePartialDefaults(string partialName) 92 | { 93 | var partialDefaults = new List(); 94 | var scopeChunks = GetViewChunks(); 95 | var renderPartialChunks = scopeChunks.SelectMany(sc => ((ScopeChunk)sc).Body).Where(c => c is RenderPartialChunk); 96 | var partialChunk = renderPartialChunks.Where(pc => ((RenderPartialChunk)pc).Name == String.Format("_{0}", partialName)).FirstOrDefault() as RenderPartialChunk; 97 | if (partialChunk == null) return partialDefaults; 98 | 99 | var paramenters = partialChunk.FileContext.Contents.Where(c => c is DefaultVariableChunk); 100 | paramenters.ToList().ForEach(p => partialDefaults.Add(((DefaultVariableChunk)p).Name)); 101 | return partialDefaults; 102 | } 103 | 104 | public IList GetContentNames() 105 | { 106 | var contentNames = new List(); 107 | var contentChunks = GetAllChunks(); 108 | contentChunks.ToList().ForEach(x => contentNames.Add((x.Name))); 109 | return contentNames; 110 | } 111 | 112 | public IList GetLocalMacros() 113 | { 114 | var localMacros = new List(); 115 | var locals = GetViewChunks(); 116 | locals.ToList().ForEach(x => localMacros.Add(x.Name)); 117 | return localMacros; 118 | } 119 | 120 | public IList GetMacroParameters(string macroName) 121 | { 122 | var macroParams = new List(); 123 | var macro = GetViewChunks().Where(chunk => chunk.Name == macroName).FirstOrDefault(); 124 | if (macro == null) return macroParams; 125 | ((MacroChunk)macro).Parameters.ToList().ForEach(p => macroParams.Add(p.Name)); 126 | return macroParams; 127 | } 128 | 129 | public TypeNavigator GetTypeNavigator() 130 | { 131 | if (_typeNavigator != null) return _typeNavigator; 132 | return _typeNavigator = new TypeNavigator(_projectExplorer.GetProjectReferencedTypes()); 133 | } 134 | 135 | public IList GetMembers() 136 | { 137 | 138 | return new List() { "Testing", "123" }; 139 | } 140 | 141 | public void InvalidateView(string newContent) 142 | { 143 | _projectExplorer.SetViewContent(_viewPath, newContent); 144 | _viewLoader.EvictEntry(_viewPath); 145 | } 146 | 147 | private IEnumerable GetViewChunks() 148 | { 149 | var chunks = 150 | LoadChunks(_viewPath) 151 | .Where(chunk => chunk is T).Cast(); 152 | return chunks; 153 | } 154 | 155 | private IList LoadChunks(string viewPath) 156 | { 157 | try 158 | { 159 | return _viewLoader.Load(viewPath) ?? new List(); 160 | } 161 | catch (CompilerException) 162 | { 163 | return new List(); 164 | } 165 | } 166 | 167 | private IEnumerable GetAllChunks() 168 | { 169 | LoadChunks(_viewPath); 170 | var allChunks = 171 | _viewLoader.GetEverythingLoaded() 172 | .SelectMany(list => list) 173 | .Where(chunk => chunk is T).Cast(); 174 | return allChunks; 175 | } 176 | 177 | private bool TryLoadMaster(string masterFile) 178 | { 179 | var locator = new DefaultTemplateLocator(); 180 | var master = locator.LocateMasterFile(_viewLoader.ViewFolder, masterFile); 181 | 182 | if (master.ViewFile == null) return false; 183 | 184 | LoadChunks(master.Path); 185 | return true; 186 | } 187 | 188 | private void InitViewChunks() 189 | { 190 | if (_viewLoader == null) return; 191 | 192 | var useMaster = GetViewChunks().FirstOrDefault(); 193 | if (useMaster != null && TryLoadMaster(useMaster.Name)) return; 194 | 195 | var controllerName = Path.GetDirectoryName(_viewPath); 196 | if (TryLoadMaster(controllerName)) return; 197 | 198 | TryLoadMaster("Application"); 199 | 200 | } 201 | 202 | private IEnumerable GetPossibleMasterFiles(string folder) 203 | { 204 | var possibleMasters = new List(); 205 | var masterFilePaths = _viewLoader.ViewFolder.ListViews(folder).Where(filePath => filePath.IsNonPartialSparkFile()); 206 | masterFilePaths.ToList().ForEach(x => possibleMasters.Add(Path.GetFileNameWithoutExtension(x))); 207 | return possibleMasters; 208 | } 209 | 210 | } 211 | } 212 | -------------------------------------------------------------------------------- /src/SparkSense/Presenter/SparkSensePresenter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.Language.Intellisense; 3 | using Microsoft.VisualStudio.Text.Adornments; 4 | using Microsoft.VisualStudio.Text; 5 | using System.Windows; 6 | using System.Windows.Data; 7 | 8 | namespace SparkSense.Presenter 9 | { 10 | public class SparkSensePresenter : IPopupIntellisensePresenter, IIntellisenseCommandTarget 11 | { 12 | private ICompletionSession _completionSession; 13 | private ITrackingSpan _presentationSpan; 14 | private SparkSenseView _view; 15 | 16 | public SparkSensePresenter(ICompletionSession completionSession) 17 | { 18 | _view = new SparkSenseView(this); 19 | InitCompletionSession(completionSession); 20 | InitCompletionItems(); 21 | } 22 | 23 | public CollectionViewSource Items { get; private set; } 24 | 25 | private void InitCompletionSession(ICompletionSession completionSession) 26 | { 27 | _completionSession = completionSession; 28 | if (_completionSession == null) return; 29 | _completionSession.SelectedCompletionSet.SelectionStatusChanged += SelectedCompletionSet_SelectionStatusChanged; 30 | _completionSession.Dismissed += CompletionSession_Dismissed; 31 | } 32 | 33 | private void InitCompletionItems() 34 | { 35 | Items = new CollectionViewSource(); 36 | Items.Source = _completionSession.SelectedCompletionSet.Completions; 37 | 38 | if (!IsCompletionListValid()) return; 39 | Items.View.MoveCurrentToPrevious(); 40 | } 41 | 42 | private void SelectedCompletionSet_SelectionStatusChanged(object sender, ValueChangedEventArgs e) 43 | { 44 | if (!IsCompletionListValid()) return; 45 | 46 | if (e.NewValue.IsSelected && e.NewValue.Completion != Items.View.CurrentItem) 47 | Items.View.MoveCurrentTo(e.NewValue.Completion); 48 | } 49 | 50 | private void CompletionSession_Dismissed(object sender, EventArgs e) 51 | { 52 | if (_completionSession == null) return; 53 | _completionSession.SelectedCompletionSet.SelectionStatusChanged -= SelectedCompletionSet_SelectionStatusChanged; 54 | _completionSession.Dismissed -= CompletionSession_Dismissed; 55 | } 56 | 57 | private void Move(int offset) 58 | { 59 | if (!IsCompletionListValid()) return; 60 | 61 | var newPosition = Items.View.CurrentPosition + offset; 62 | if (PositionIsInBounds(newPosition)) 63 | Items.View.MoveCurrentToPosition(newPosition); 64 | else 65 | MoveToFirstOrLast(newPosition); 66 | 67 | _completionSession.SelectedCompletionSet.SelectionStatus = new CompletionSelectionStatus((Completion)Items.View.CurrentItem, true, true); 68 | } 69 | 70 | private void MoveToFirstOrLast(int newPosition) 71 | { 72 | if (newPosition < 0) 73 | Items.View.MoveCurrentToFirst(); 74 | else 75 | Items.View.MoveCurrentToLast(); 76 | 77 | if (Items.View.IsCurrentBeforeFirst) Items.View.MoveCurrentToFirst(); 78 | if (Items.View.IsCurrentAfterLast) Items.View.MoveCurrentToLast(); 79 | } 80 | 81 | private bool IsCompletionListValid() 82 | { 83 | return Items != null && Items.View != null && _completionSession != null; 84 | } 85 | 86 | private bool PositionIsInBounds(int newPosition) 87 | { 88 | return newPosition < ((ListCollectionView)Items.View).Count && newPosition > -1; 89 | } 90 | 91 | private ITrackingSpan GetPresentationSpan() 92 | { 93 | SnapshotSpan span = _completionSession.SelectedCompletionSet.ApplicableTo.GetSpan(_completionSession.TextView.TextSnapshot); 94 | NormalizedSnapshotSpanCollection spans = _completionSession.TextView.BufferGraph.MapUpToBuffer(span, _completionSession.SelectedCompletionSet.ApplicableTo.TrackingMode, _completionSession.TextView.TextBuffer); 95 | if (spans.Count <= 0) 96 | { 97 | throw new InvalidOperationException("Completion Session Applicable To Span is invalid. It doesn't map to a span in the session's text view."); 98 | } 99 | SnapshotSpan span2 = spans[0]; 100 | return _completionSession.TextView.TextBuffer.CurrentSnapshot.CreateTrackingSpan(span2.Span, SpanTrackingMode.EdgeInclusive); 101 | } 102 | 103 | #region IPopupIntellisensePresenter Members 104 | 105 | public event EventHandler> PopupStylesChanged; 106 | public event EventHandler SurfaceElementChanged; 107 | public event EventHandler PresentationSpanChanged; 108 | 109 | public double Opacity 110 | { 111 | get 112 | { 113 | return _view.Opacity; 114 | } 115 | set 116 | { 117 | _view.Opacity = value; 118 | } 119 | } 120 | 121 | public PopupStyles PopupStyles 122 | { 123 | get { return PopupStyles.PositionClosest; } 124 | } 125 | 126 | public ITrackingSpan PresentationSpan 127 | { 128 | get 129 | { 130 | if (_presentationSpan == null) 131 | _presentationSpan = GetPresentationSpan(); 132 | return _presentationSpan; 133 | } 134 | } 135 | 136 | public string SpaceReservationManagerName 137 | { 138 | get { return "completion"; } 139 | } 140 | 141 | public UIElement SurfaceElement 142 | { 143 | get { return _view; } 144 | } 145 | #endregion 146 | 147 | #region IIntellisensePresenter Members 148 | 149 | public IIntellisenseSession Session 150 | { 151 | get { return _completionSession; } 152 | } 153 | 154 | #endregion 155 | 156 | #region IIntellisenseCommandTarget Members 157 | 158 | public bool ExecuteKeyboardCommand(IntellisenseKeyboardCommand command) 159 | { 160 | switch (command) 161 | { 162 | case IntellisenseKeyboardCommand.Up: 163 | Move(-1); 164 | return true; 165 | case IntellisenseKeyboardCommand.Down: 166 | Move(1); 167 | return true; 168 | case IntellisenseKeyboardCommand.PageUp: 169 | Move(-10); 170 | return true; 171 | case IntellisenseKeyboardCommand.PageDown: 172 | Move(10); 173 | return true; 174 | case IntellisenseKeyboardCommand.Enter: 175 | _completionSession.Commit(); 176 | return true; 177 | case IntellisenseKeyboardCommand.Escape: 178 | _completionSession.Dismiss(); 179 | return true; 180 | //Maybe one day we'll do something with these below 181 | case IntellisenseKeyboardCommand.End: 182 | case IntellisenseKeyboardCommand.Home: 183 | case IntellisenseKeyboardCommand.DecreaseFilterLevel: 184 | case IntellisenseKeyboardCommand.IncreaseFilterLevel: 185 | case IntellisenseKeyboardCommand.TopLine: 186 | case IntellisenseKeyboardCommand.BottomLine: 187 | break; 188 | } 189 | return false; 190 | } 191 | 192 | #endregion 193 | 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /src/SparkSense/Presenter/SparkSensePresenterListener.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.Language.Intellisense; 2 | using Microsoft.VisualStudio.Utilities; 3 | using System.ComponentModel.Composition; 4 | 5 | namespace SparkSense.Presenter 6 | { 7 | [Export(typeof(IIntellisensePresenterProvider))] 8 | [ContentType("Spark")] 9 | [ContentType("HTML")] 10 | [Order(Before="Default")] 11 | [Name("SparkSense Presenter")] 12 | public class SparkSensePresenterListener : IIntellisensePresenterProvider 13 | { 14 | 15 | #region IIntellisensePresenterProvider Members 16 | 17 | public IIntellisensePresenter TryCreateIntellisensePresenter(IIntellisenseSession session) 18 | { 19 | ICompletionSession completionSession = session as ICompletionSession; 20 | if (completionSession == null) return null; 21 | 22 | return null; // return new SparkSensePresenter(completionSession); 23 | } 24 | 25 | #endregion 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/SparkSense/Presenter/SparkSenseView.xaml: -------------------------------------------------------------------------------- 1 |  8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/SparkSense/Presenter/SparkSenseView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Windows; 6 | using System.Windows.Controls; 7 | using System.Windows.Data; 8 | using System.Windows.Documents; 9 | using System.Windows.Input; 10 | using System.Windows.Media; 11 | using System.Windows.Media.Imaging; 12 | using System.Windows.Navigation; 13 | using System.Windows.Shapes; 14 | 15 | namespace SparkSense.Presenter 16 | { 17 | public partial class SparkSenseView : UserControl 18 | { 19 | private SparkSensePresenter _presenter; 20 | public SparkSenseView(SparkSensePresenter presenter) 21 | { 22 | InitializeComponent(); 23 | _presenter = presenter; 24 | DataContext = _presenter; 25 | listViewCompletions.SelectionChanged += (s, e) => listViewCompletions.ScrollIntoView(listViewCompletions.SelectedItem); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/SparkSense/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("SparkSense")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("SparkSense")] 12 | [assembly: AssemblyCopyright("")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // Version information for an assembly consists of the following four values: 22 | // 23 | // Major Version 24 | // Minor Version 25 | // Build Number 26 | // Revision 27 | // 28 | // You can specify all the values or you can default the Build and Revision Numbers 29 | // by using the '*' as shown below: 30 | // [assembly: AssemblyVersion("1.0.*")] 31 | [assembly: AssemblyVersion("1.0.0.0")] 32 | [assembly: AssemblyFileVersion("1.0.0.0")] 33 | -------------------------------------------------------------------------------- /src/SparkSense/Resources/Class.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SparkViewEngine/SparkSense/08c46f516a03d7276350c1cf7ceea043673008a6/src/SparkSense/Resources/Class.png -------------------------------------------------------------------------------- /src/SparkSense/Resources/Event.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SparkViewEngine/SparkSense/08c46f516a03d7276350c1cf7ceea043673008a6/src/SparkSense/Resources/Event.png -------------------------------------------------------------------------------- /src/SparkSense/Resources/Field.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SparkViewEngine/SparkSense/08c46f516a03d7276350c1cf7ceea043673008a6/src/SparkSense/Resources/Field.png -------------------------------------------------------------------------------- /src/SparkSense/Resources/Method.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SparkViewEngine/SparkSense/08c46f516a03d7276350c1cf7ceea043673008a6/src/SparkSense/Resources/Method.png -------------------------------------------------------------------------------- /src/SparkSense/Resources/Namespace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SparkViewEngine/SparkSense/08c46f516a03d7276350c1cf7ceea043673008a6/src/SparkSense/Resources/Namespace.png -------------------------------------------------------------------------------- /src/SparkSense/Resources/Property.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SparkViewEngine/SparkSense/08c46f516a03d7276350c1cf7ceea043673008a6/src/SparkSense/Resources/Property.png -------------------------------------------------------------------------------- /src/SparkSense/Resources/SparkAttribute.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SparkViewEngine/SparkSense/08c46f516a03d7276350c1cf7ceea043673008a6/src/SparkSense/Resources/SparkAttribute.png -------------------------------------------------------------------------------- /src/SparkSense/Resources/SparkContentName.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SparkViewEngine/SparkSense/08c46f516a03d7276350c1cf7ceea043673008a6/src/SparkSense/Resources/SparkContentName.png -------------------------------------------------------------------------------- /src/SparkSense/Resources/SparkElement.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SparkViewEngine/SparkSense/08c46f516a03d7276350c1cf7ceea043673008a6/src/SparkSense/Resources/SparkElement.png -------------------------------------------------------------------------------- /src/SparkSense/Resources/SparkGlobalVariable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SparkViewEngine/SparkSense/08c46f516a03d7276350c1cf7ceea043673008a6/src/SparkSense/Resources/SparkGlobalVariable.png -------------------------------------------------------------------------------- /src/SparkSense/Resources/SparkLocalVariable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SparkViewEngine/SparkSense/08c46f516a03d7276350c1cf7ceea043673008a6/src/SparkSense/Resources/SparkLocalVariable.png -------------------------------------------------------------------------------- /src/SparkSense/Resources/SparkMacro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SparkViewEngine/SparkSense/08c46f516a03d7276350c1cf7ceea043673008a6/src/SparkSense/Resources/SparkMacro.png -------------------------------------------------------------------------------- /src/SparkSense/Resources/SparkMacroParameter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SparkViewEngine/SparkSense/08c46f516a03d7276350c1cf7ceea043673008a6/src/SparkSense/Resources/SparkMacroParameter.png -------------------------------------------------------------------------------- /src/SparkSense/Resources/SparkPartial.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SparkViewEngine/SparkSense/08c46f516a03d7276350c1cf7ceea043673008a6/src/SparkSense/Resources/SparkPartial.png -------------------------------------------------------------------------------- /src/SparkSense/Resources/SparkPartialParameter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SparkViewEngine/SparkSense/08c46f516a03d7276350c1cf7ceea043673008a6/src/SparkSense/Resources/SparkPartialParameter.png -------------------------------------------------------------------------------- /src/SparkSense/Resources/SparkSenseViewResources.xaml: -------------------------------------------------------------------------------- 1 |  5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /src/SparkSense/SignatureRecognition/SparkSignatureHelpCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using Microsoft.VisualStudio; 4 | using Microsoft.VisualStudio.Language.Intellisense; 5 | using Microsoft.VisualStudio.OLE.Interop; 6 | using Microsoft.VisualStudio.Text; 7 | using Microsoft.VisualStudio.Text.Editor; 8 | using Microsoft.VisualStudio.Text.Operations; 9 | using Microsoft.VisualStudio.TextManager.Interop; 10 | 11 | namespace SparkSense.SignatureRecognition 12 | { 13 | internal class SparkSignatureHelpCommand : IOleCommandTarget 14 | { 15 | private readonly ISignatureHelpBroker _broker; 16 | private readonly ITextStructureNavigator _navigator; 17 | private readonly IWpfTextView _textView; 18 | private IOleCommandTarget _nextCommand; 19 | private ISignatureHelpSession _session; 20 | 21 | public SparkSignatureHelpCommand(IVsTextView textViewAdapter, IWpfTextView textView, ITextStructureNavigator navigator, ISignatureHelpBroker broker) 22 | { 23 | _textView = textView; 24 | _navigator = navigator; 25 | _broker = broker; 26 | 27 | ChainTheNextCommand(textViewAdapter); 28 | } 29 | 30 | #region IOleCommandTarget Members 31 | 32 | public int QueryStatus(ref Guid cmdGroup, uint cmds, OLECMD[] prgCmds, IntPtr cmdText) 33 | { 34 | return _nextCommand.QueryStatus(cmdGroup, cmds, prgCmds, cmdText); 35 | } 36 | 37 | public int Exec(ref Guid cmdGroup, uint cmdId, uint cmdExecOpt, IntPtr pvaIn, IntPtr pvaOut) 38 | { 39 | char inputCharacter = char.MinValue; 40 | 41 | if (cmdGroup == VSConstants.VSStd2K && cmdId == (uint) VSConstants.VSStd2KCmdID.TYPECHAR) 42 | { 43 | inputCharacter = (char) (ushort) Marshal.GetObjectForNativeVariant(pvaIn); 44 | if (inputCharacter.Equals(' ')) 45 | { 46 | SnapshotPoint currentPosition = _textView.Caret.Position.BufferPosition - 1; 47 | TextExtent extentOfWord = _navigator.GetExtentOfWord(currentPosition); 48 | string tagName = extentOfWord.Span.GetText(); 49 | _session = _broker.TriggerSignatureHelp(_textView); 50 | } 51 | else if (inputCharacter.Equals('>') && _session != null) 52 | { 53 | _session.Dismiss(); 54 | _session = null; 55 | } 56 | } 57 | return _nextCommand.Exec(cmdGroup, cmdId, cmdExecOpt, pvaIn, pvaOut); 58 | } 59 | 60 | #endregion 61 | 62 | private void ChainTheNextCommand(IVsTextView textViewAdapter) 63 | { 64 | textViewAdapter.AddCommandFilter(this, out _nextCommand); 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /src/SparkSense/SignatureRecognition/SparkSignatureHelpCommandListener.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.Composition; 3 | using Microsoft.VisualStudio.Editor; 4 | using Microsoft.VisualStudio.Language.Intellisense; 5 | using Microsoft.VisualStudio.Text.Editor; 6 | using Microsoft.VisualStudio.Text.Operations; 7 | using Microsoft.VisualStudio.TextManager.Interop; 8 | using Microsoft.VisualStudio.Utilities; 9 | 10 | namespace SparkSense.SignatureRecognition 11 | { 12 | [Export(typeof (IVsTextViewCreationListener))] 13 | [Name("Spark Tag Signature Help Listener")] 14 | [TextViewRole(PredefinedTextViewRoles.Editable)] 15 | [ContentType("spark")] 16 | [ContentType("HTML")] 17 | internal class SparkSignatureHelpCommandListener : IVsTextViewCreationListener 18 | { 19 | [Import] internal IVsEditorAdaptersFactoryService AdapterService = null; 20 | [Import] internal ISignatureHelpBroker Broker = null; 21 | [Import] internal ITextStructureNavigatorSelectorService NavigatorService = null; 22 | 23 | #region IVsTextViewCreationListener Members 24 | 25 | public void VsTextViewCreated(IVsTextView textViewAdapter) 26 | { 27 | IWpfTextView textView = AdapterService.GetWpfTextView(textViewAdapter); 28 | if (textView == null) return; 29 | ITextStructureNavigator navigator = NavigatorService.GetTextStructureNavigator(textView.TextBuffer); 30 | 31 | Func createCommand = () => new SparkSignatureHelpCommand(textViewAdapter, textView, navigator, Broker); 32 | textView.Properties.GetOrCreateSingletonProperty(createCommand); 33 | } 34 | 35 | #endregion 36 | } 37 | } -------------------------------------------------------------------------------- /src/SparkSense/SignatureRecognition/SparkSignatureHelpSource.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.ObjectModel; 4 | using Microsoft.VisualStudio.Language.Intellisense; 5 | using Microsoft.VisualStudio.Text; 6 | 7 | namespace SparkSense.SignatureRecognition 8 | { 9 | internal class SparkSignatureHelpSource : ISignatureHelpSource 10 | { 11 | private readonly ITextBuffer _textBuffer; 12 | private bool _isDisposed; 13 | 14 | public SparkSignatureHelpSource(ITextBuffer textBuffer) 15 | { 16 | _textBuffer = textBuffer; 17 | } 18 | 19 | #region ISignatureHelpSource Members 20 | 21 | public void AugmentSignatureHelpSession(ISignatureHelpSession session, IList signatures) 22 | { 23 | ITextSnapshot currentSnapshot = _textBuffer.CurrentSnapshot; 24 | int currentPosition = session.GetTriggerPoint(_textBuffer).GetPosition(currentSnapshot); 25 | ITrackingSpan currentApplicableSpan = currentSnapshot.CreateTrackingSpan(new Span(currentPosition, 0), SpanTrackingMode.EdgeInclusive, TrackingFidelityMode.Forward); 26 | 27 | signatures.Add(CreateSignature(_textBuffer, "", "Spools all output in the content element into a named text writer", currentApplicableSpan)); 28 | signatures.Add(CreateSignature(_textBuffer, "", "Spools all output into a temporary text writer", currentApplicableSpan)); 29 | signatures.Add(CreateSignature(_textBuffer, "", "Spools all output into a temporary text writer (same as 'var')", currentApplicableSpan)); 30 | signatures.Add(CreateSignature(_textBuffer, "", "Declares local variables if a symbol of a given name is not known to be in scope", currentApplicableSpan)); 31 | } 32 | 33 | public ISignature GetBestMatch(ISignatureHelpSession session) 34 | { 35 | if (session.Signatures.Count <= 0) return null; 36 | 37 | //TODO: Rob G - Flesh this out to cover various signatures 38 | 39 | return session.Signatures[0]; 40 | } 41 | 42 | public void Dispose() 43 | { 44 | if (_isDisposed) return; 45 | 46 | GC.SuppressFinalize(this); 47 | _isDisposed = true; 48 | } 49 | 50 | #endregion 51 | 52 | private static SparkTagSignature CreateSignature(ITextBuffer textBuffer, string tagSignature, string tagDocumentation, ITrackingSpan currentApplicableSpan) 53 | { 54 | var signature = new SparkTagSignature(textBuffer, tagSignature, tagDocumentation, null); 55 | textBuffer.Changed += signature.OnTextBufferChanged; 56 | 57 | string[] parameters = tagSignature.Split(' '); 58 | IList paramList = new List(); 59 | 60 | int spanSearchStart = 0; 61 | for (int i = 1; i < parameters.Length; i++) 62 | { 63 | string param = parameters[i].Trim(); 64 | if (string.IsNullOrEmpty(param)) continue; 65 | 66 | int spanStart = tagSignature.IndexOf(param, spanSearchStart); 67 | if (spanStart >= 0) 68 | { 69 | var span = new Span(spanStart, param.Length); 70 | spanSearchStart = spanStart + param.Length; 71 | IParameter parameter = new SparkTagParameter("param doc", span, param, signature); 72 | paramList.Add(parameter); 73 | } 74 | } 75 | 76 | signature.Parameters = new ReadOnlyCollection(paramList); 77 | signature.ApplicableToSpan = currentApplicableSpan; 78 | signature.InitCurrentParameter(); 79 | return signature; 80 | } 81 | } 82 | } -------------------------------------------------------------------------------- /src/SparkSense/SignatureRecognition/SparkSignatureHelpSourceProvider.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.Composition; 2 | using Microsoft.VisualStudio.Language.Intellisense; 3 | using Microsoft.VisualStudio.Text; 4 | using Microsoft.VisualStudio.Utilities; 5 | 6 | namespace SparkSense.SignatureRecognition 7 | { 8 | [Export(typeof (ISignatureHelpSourceProvider))] 9 | [Name("Spark Tag Signature Help Source")] 10 | [ContentType("spark")] 11 | [ContentType("HTML")] 12 | internal class SparkSignatureHelpSourceProvider : ISignatureHelpSourceProvider 13 | { 14 | #region ISignatureHelpSourceProvider Members 15 | 16 | public ISignatureHelpSource TryCreateSignatureHelpSource(ITextBuffer textBuffer) 17 | { 18 | return null; //temporary 19 | //return new SparkSignatureHelpSource(textBuffer); 20 | } 21 | 22 | #endregion 23 | } 24 | } -------------------------------------------------------------------------------- /src/SparkSense/SignatureRecognition/SparkTagParameter.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.Language.Intellisense; 2 | using Microsoft.VisualStudio.Text; 3 | 4 | namespace SparkSense.SignatureRecognition 5 | { 6 | internal class SparkTagParameter : IParameter 7 | { 8 | public SparkTagParameter(string documentation, Span span, string name, ISignature signature) 9 | { 10 | Documentation = documentation; 11 | Locus = span; 12 | Name = name; 13 | Signature = signature; 14 | } 15 | 16 | #region IParameter Members 17 | 18 | public ISignature Signature { get; private set; } 19 | public string Name { get; private set; } 20 | public string Documentation { get; private set; } 21 | public Span Locus { get; private set; } 22 | public Span PrettyPrintedLocus { get; private set; } 23 | 24 | #endregion 25 | } 26 | } -------------------------------------------------------------------------------- /src/SparkSense/SignatureRecognition/SparkTagSignature.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.ObjectModel; 3 | using Microsoft.VisualStudio.Language.Intellisense; 4 | using Microsoft.VisualStudio.Text; 5 | 6 | namespace SparkSense.SignatureRecognition 7 | { 8 | internal class SparkTagSignature : ISignature 9 | { 10 | private readonly ITextBuffer _textBuffer; 11 | private IParameter _currentParameter; 12 | 13 | public SparkTagSignature(ITextBuffer textBuffer, string content, string documentation, ReadOnlyCollection parameters) 14 | { 15 | Content = content; 16 | PrettyPrintedContent = content; //TODO: Rob G - Figure this out later 17 | Documentation = documentation; 18 | Parameters = parameters; 19 | _textBuffer = textBuffer; 20 | _textBuffer.Changed += OnTextBufferChanged; 21 | } 22 | 23 | #region ISignature Members 24 | 25 | public ITrackingSpan ApplicableToSpan { get; internal set; } 26 | 27 | public string Content { get; private set; } 28 | 29 | public string PrettyPrintedContent { get; private set; } 30 | 31 | public string Documentation { get; private set; } 32 | 33 | public ReadOnlyCollection Parameters { get; internal set; } 34 | 35 | public IParameter CurrentParameter 36 | { 37 | get { return _currentParameter; } 38 | set 39 | { 40 | if (_currentParameter == value) return; 41 | IParameter previousParameter = _currentParameter; 42 | _currentParameter = value; 43 | InvokeCurrentParameterChanged(previousParameter, _currentParameter); 44 | } 45 | } 46 | 47 | public event EventHandler CurrentParameterChanged; 48 | 49 | #endregion 50 | 51 | public void InvokeCurrentParameterChanged(IParameter previousCurrentParameter, IParameter newCurrentParameter) 52 | { 53 | EventHandler handler = CurrentParameterChanged; 54 | if (handler != null) handler(this, new CurrentParameterChangedEventArgs(previousCurrentParameter, newCurrentParameter)); 55 | } 56 | 57 | internal void InitCurrentParameter() 58 | { 59 | if (Parameters.Count == 0) 60 | { 61 | CurrentParameter = null; 62 | return; 63 | } 64 | 65 | string signatureText = ApplicableToSpan.GetText(_textBuffer.CurrentSnapshot); 66 | 67 | int currentIndex = 0; 68 | int spaceCount = 0; 69 | 70 | while (currentIndex < signatureText.Length) 71 | { 72 | int commaIndex = signatureText.IndexOf(' ', currentIndex); 73 | if (commaIndex == -1) 74 | { 75 | break; 76 | } 77 | spaceCount++; 78 | currentIndex = commaIndex + 1; 79 | } 80 | 81 | CurrentParameter = spaceCount < Parameters.Count 82 | ? Parameters[spaceCount] 83 | : Parameters[Parameters.Count - 1]; 84 | } 85 | 86 | internal void OnTextBufferChanged(object sender, TextContentChangedEventArgs e) 87 | { 88 | InitCurrentParameter(); 89 | } 90 | } 91 | } -------------------------------------------------------------------------------- /src/SparkSense/SparkIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SparkViewEngine/SparkSense/08c46f516a03d7276350c1cf7ceea043673008a6/src/SparkSense/SparkIcon.png -------------------------------------------------------------------------------- /src/SparkSense/SparkLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SparkViewEngine/SparkSense/08c46f516a03d7276350c1cf7ceea043673008a6/src/SparkSense/SparkLogo.png -------------------------------------------------------------------------------- /src/SparkSense/SparkServiceProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.Composition; 3 | using System.Diagnostics; 4 | using EnvDTE; 5 | using Microsoft.VisualStudio.Editor; 6 | using Microsoft.VisualStudio.Shell; 7 | using Microsoft.VisualStudio.Shell.Design; 8 | using SparkSense.Parsing; 9 | 10 | namespace SparkSense 11 | { 12 | public interface ISparkServiceProvider 13 | { 14 | IProjectExplorer ProjectExplorer { get; } 15 | DTE VsEnvironment { get; } 16 | IVsEditorAdaptersFactoryService AdaptersFactoryService { get; } 17 | DynamicTypeService TypeService { get; } 18 | T GetService(); 19 | T GetService(Type serviceType); 20 | } 21 | 22 | [Export(typeof (ISparkServiceProvider))] 23 | public class SparkServiceProvider : ISparkServiceProvider 24 | { 25 | [Import] private IVsEditorAdaptersFactoryService _adaptersFactoryService; 26 | private IProjectExplorer _projectExplorer; 27 | [Import(typeof (SVsServiceProvider))] private IServiceProvider _serviceProvider; 28 | private DynamicTypeService _typeService; 29 | private DTE _vsEnvironment; 30 | 31 | #region ISparkServiceProvider Members 32 | 33 | public T GetService() 34 | { 35 | return (T) _serviceProvider.GetService(typeof (T)); 36 | } 37 | 38 | public T GetService(Type serviceType) 39 | { 40 | return (T) _serviceProvider.GetService(serviceType); 41 | } 42 | 43 | public IVsEditorAdaptersFactoryService AdaptersFactoryService 44 | { 45 | get { return _adaptersFactoryService; } 46 | } 47 | 48 | public IProjectExplorer ProjectExplorer 49 | { 50 | get 51 | { 52 | if (_projectExplorer == null) 53 | _projectExplorer = VsEnvironment != null ? new ProjectExplorer(this) : null; 54 | return _projectExplorer; 55 | } 56 | } 57 | 58 | public DTE VsEnvironment 59 | { 60 | get 61 | { 62 | if (_vsEnvironment == null) 63 | _vsEnvironment = GetService(); 64 | return _vsEnvironment; 65 | } 66 | } 67 | 68 | public DynamicTypeService TypeService 69 | { 70 | get 71 | { 72 | if (_typeService == null) 73 | { 74 | _typeService = GetService(); 75 | Debug.Assert(_typeService != null, "No dynamic type service available."); 76 | } 77 | return _typeService; 78 | } 79 | } 80 | 81 | #endregion 82 | } 83 | } -------------------------------------------------------------------------------- /src/SparkSense/StatementCompletion/CompletionExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using Microsoft.VisualStudio; 4 | using Microsoft.VisualStudio.Text; 5 | using Microsoft.VisualStudio.Text.Editor; 6 | using Microsoft.VisualStudio.Language.Intellisense; 7 | using System.Collections.Generic; 8 | 9 | 10 | namespace SparkSense.StatementCompletion 11 | { 12 | public static class CompletionExtensions 13 | { 14 | public static char GetInputCharacter(this uint key, Guid cmdGroup, IntPtr pvaIn) 15 | { 16 | if (cmdGroup == VSConstants.VSStd2K && key == (uint)VSConstants.VSStd2KCmdID.TYPECHAR) 17 | return (char)(ushort)Marshal.GetObjectForNativeVariant(pvaIn); 18 | return char.MinValue; 19 | } 20 | 21 | public static bool IsACommitCharacter(this uint key, char inputCharacter) 22 | { 23 | return key == (uint)VSConstants.VSStd2KCmdID.RETURN || key == (uint)VSConstants.VSStd2KCmdID.TAB || char.IsWhiteSpace(inputCharacter) || char.IsPunctuation(inputCharacter); 24 | } 25 | 26 | public static bool IsACommitCharacterWithNoOutput(this uint key, char inputCharacter) 27 | { 28 | return key == (uint)VSConstants.VSStd2KCmdID.RETURN || key == (uint)VSConstants.VSStd2KCmdID.TAB; 29 | } 30 | 31 | public static bool IsADeletionCharacter(this uint key) 32 | { 33 | return key == (uint)VSConstants.VSStd2KCmdID.BACKSPACE || key == (uint)VSConstants.VSStd2KCmdID.DELETE; 34 | } 35 | 36 | public static bool IsAMovementCharacter(this uint key) 37 | { 38 | return key == (uint)VSConstants.VSStd2KCmdID.LEFT || key == (uint)VSConstants.VSStd2KCmdID.RIGHT; 39 | } 40 | 41 | public static bool IsStartCompletionCharacter(this uint key) 42 | { 43 | return key == (uint)VSConstants.VSStd2KCmdID.COMPLETEWORD; 44 | } 45 | 46 | public static bool HasMovedOutOfIntelliSenseRange(this uint key, ITextView textView, ICompletionSession session) 47 | { 48 | if (textView == null) return true; 49 | 50 | var textBuffer = textView.TextBuffer; 51 | var caretPosition = textView.Caret.Position.BufferPosition.Position; 52 | var triggerPoint = session.GetTriggerPoint(textBuffer).GetPoint(textBuffer.CurrentSnapshot); 53 | ITrackingSpan completionSpan = triggerPoint.Snapshot.CreateTrackingSpan(new Span(triggerPoint, 0), SpanTrackingMode.EdgeInclusive); 54 | int completionSpanLength = completionSpan.GetSpan(textView.TextSnapshot).Length; 55 | 56 | switch (key) 57 | { 58 | case (uint)VSConstants.VSStd2KCmdID.LEFT: 59 | return caretPosition < triggerPoint; 60 | case (uint)VSConstants.VSStd2KCmdID.RIGHT: 61 | return caretPosition > triggerPoint + completionSpanLength; 62 | default: 63 | return false; 64 | } 65 | } 66 | 67 | public static List SortAlphabetically(this List toSort) { 68 | if(toSort != null && toSort.Count > 1) 69 | toSort.Sort((c1, c2) => c1.DisplayText.CompareTo(c2.DisplayText)); 70 | return toSort; 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/SparkSense/StatementCompletion/CompletionListener.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.Language.Intellisense; 2 | using Microsoft.VisualStudio.Text; 3 | using Microsoft.VisualStudio.Utilities; 4 | using System.ComponentModel.Composition; 5 | 6 | namespace SparkSense.StatementCompletion 7 | { 8 | [Export(typeof(ICompletionSourceProvider))] 9 | [ContentType("spark")] 10 | [ContentType("HTML")] 11 | [Name("Spark Tag Completion")] 12 | public class CompletionListener : ICompletionSourceProvider 13 | { 14 | [Import] 15 | public ISparkServiceProvider ServiceProvider { get; set; } 16 | 17 | #region ICompletionSourceProvider Members 18 | 19 | public ICompletionSource TryCreateCompletionSource(ITextBuffer textBuffer) 20 | { 21 | return ServiceProvider.ProjectExplorer != null ? new CompletionSource(textBuffer, ServiceProvider.ProjectExplorer) : null; 22 | } 23 | 24 | #endregion 25 | } 26 | } -------------------------------------------------------------------------------- /src/SparkSense/StatementCompletion/CompletionSessionManager.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.Language.Intellisense; 2 | using Microsoft.VisualStudio.Text; 3 | using Microsoft.VisualStudio.Text.Editor; 4 | using Microsoft.VisualStudio.Text.Operations; 5 | using Spark.Parser.Markup; 6 | using SparkSense.Parsing; 7 | using System; 8 | using System.Collections.Generic; 9 | 10 | namespace SparkSense.StatementCompletion 11 | { 12 | public class CompletionSessionManager 13 | { 14 | private ICompletionBroker _completionBroker; 15 | private IWpfTextView _textView; 16 | private ICompletionSession _sparkOnlySession; 17 | private ITextStructureNavigator _textNavigator; 18 | private ITrackingSpan _trackingSpan; 19 | private bool _scanForNewSession; 20 | private Type _currentContext; 21 | 22 | public CompletionSessionManager(ICompletionBroker broker, IWpfTextView textView, ITextStructureNavigator textNavigator) 23 | { 24 | if (broker == null) throw new ArgumentNullException("broker", "Completion Broker is null."); 25 | if (textView == null) throw new ArgumentNullException("textView", "Text View is null."); 26 | if (textNavigator == null) throw new ArgumentNullException("textNavigator", "Text Navigator is null."); 27 | 28 | _completionBroker = broker; 29 | _textView = textView; 30 | _textNavigator = textNavigator; 31 | } 32 | 33 | public bool IsCompletionSessionActive() 34 | { 35 | return _completionBroker.IsCompletionActive(_textView); 36 | } 37 | 38 | public bool IsSparkOnlySessionActive() 39 | { 40 | return _sparkOnlySession != null && !_sparkOnlySession.IsDismissed; 41 | } 42 | 43 | public bool IsCompletionCommitted(uint key, char inputCharacter) 44 | { 45 | if (!(key.IsACommitCharacter(inputCharacter) && IsSparkOnlySessionActive())) 46 | return false; 47 | 48 | if (_sparkOnlySession.SelectedCompletionSet.SelectionStatus.IsSelected) 49 | { 50 | _sparkOnlySession.Commit(); 51 | return key.IsACommitCharacterWithNoOutput(inputCharacter); 52 | } 53 | _sparkOnlySession.Dismiss(); 54 | return false; 55 | } 56 | 57 | public bool IsCompletionStarted(uint key, char inputCharacter) 58 | { 59 | var caretPoint = _textView.Caret.Position.BufferPosition; 60 | if (!_scanForNewSession && inputCharacter == Char.MinValue && !key.IsStartCompletionCharacter()) return false; 61 | if (IsCompletionSessionActive()) return true; 62 | 63 | if (!IsSparkSyntax(caretPoint.Position)) 64 | return IsMovementOrDeletionHandled(key); 65 | 66 | if (IsSparkOnlySessionActive() || StartCompletionSession()) 67 | _sparkOnlySession.Filter(); 68 | _scanForNewSession = false; 69 | return true; 70 | } 71 | 72 | private bool IsSparkSyntax(int caretPosition) 73 | { 74 | //TODO: Rob G This is a general catch all trap because if something goes wrong during the Beta. 75 | // We don't was Visual Studio to explode, but rather just that intellisense stops working for 76 | // this particular key press - it'll try again next time. The Beta will drive out most syntax issues. 77 | try 78 | { 79 | _currentContext = SparkSyntax.ParseContext(_textView.TextBuffer.CurrentSnapshot.GetText(), caretPosition); 80 | return _currentContext != null && _currentContext != typeof(TextNode); 81 | } 82 | catch 83 | { 84 | return false; 85 | } 86 | } 87 | 88 | private bool IsMovementOrDeletionHandled(uint key) 89 | { 90 | if (ShouldDismissCompletion(key)) 91 | _sparkOnlySession.Dismiss(); 92 | 93 | if (!key.IsADeletionCharacter()) return false; 94 | 95 | if (!IsSparkOnlySessionActive()) return true; 96 | 97 | _sparkOnlySession.Filter(); 98 | return true; 99 | } 100 | 101 | private bool ShouldDismissCompletion(uint key) 102 | { 103 | return 104 | IsSparkOnlySessionActive() && 105 | key.IsAMovementCharacter() && 106 | key.HasMovedOutOfIntelliSenseRange(_textView, _sparkOnlySession); 107 | } 108 | 109 | public bool StartCompletionSession() 110 | { 111 | if (!TryCreateCompletionSession()) return false; 112 | AddCompletionSourceProperties( 113 | new Dictionary 114 | { 115 | {typeof(ITrackingSpan), _trackingSpan} 116 | }); 117 | 118 | _sparkOnlySession.Dismissed += OnSessionDismissed; 119 | _sparkOnlySession.Committed += OnSessionCommitted; 120 | _sparkOnlySession.Start(); 121 | return IsSparkOnlySessionActive(); 122 | } 123 | 124 | public bool TryCreateCompletionSession() 125 | { 126 | var caret = _textView.Caret.Position.Point.GetPoint( 127 | textBuffer => (textBuffer.ContentType.IsOfType("projection")), PositionAffinity.Predecessor); 128 | if (!caret.HasValue) return false; 129 | 130 | var trackingPoint = caret.Value.Snapshot.CreateTrackingPoint(caret.Value.Position, PointTrackingMode.Positive); 131 | 132 | GetTrackingSpan(caret.Value.Snapshot, caret.Value.Position); 133 | 134 | _sparkOnlySession = _completionBroker.CreateCompletionSession(_textView, trackingPoint, true); 135 | return _sparkOnlySession != null; 136 | } 137 | 138 | private void GetTrackingSpan(ITextSnapshot snapshot, int triggerPoint) 139 | { 140 | ITextSnapshotLine line = snapshot.GetLineFromPosition(triggerPoint); 141 | string lineString = line.GetText(); 142 | var stopChars = new char[] {' ', '\t', '{', '}', '.', '"', ':'}; 143 | int start = lineString.Substring(0, triggerPoint - line.Start.Position).LastIndexOfAny(stopChars) + line.Start.Position + 1; 144 | int length = lineString.Substring(triggerPoint - line.Start.Position).IndexOfAny(stopChars) + triggerPoint - start; 145 | _trackingSpan = snapshot.CreateTrackingSpan(start, length < 0 ? 0 : length, SpanTrackingMode.EdgeInclusive); 146 | } 147 | 148 | public void AddCompletionSourceProperties(Dictionary properties) 149 | { 150 | if (properties == null) return; 151 | foreach (var property in properties) 152 | _sparkOnlySession.Properties.AddProperty(property.Key, property.Value); 153 | } 154 | 155 | private bool IsCompletionChar(char completionChar) 156 | { 157 | var point = _sparkOnlySession.TextView.Caret.Position.BufferPosition; 158 | return point.Position > 1 && (point - 1).GetChar() == completionChar; 159 | } 160 | private void ScanForPossibleNewSession() 161 | { 162 | if (!IsSparkOnlySessionActive()) return; 163 | if (!IsCompletionChar(Constants.DOUBLE_QUOTE) 164 | && !IsCompletionChar(Constants.SINGLE_QUOTE)) return; 165 | 166 | _scanForNewSession = true; 167 | _sparkOnlySession.TextView.Caret.MoveToPreviousCaretPosition(); 168 | } 169 | private void OnSessionCommitted(object sender, EventArgs e) 170 | { 171 | ScanForPossibleNewSession(); 172 | _sparkOnlySession.Dismiss(); 173 | } 174 | 175 | private void OnSessionDismissed(object sender, EventArgs e) 176 | { 177 | _sparkOnlySession.Dismissed -= OnSessionDismissed; 178 | _sparkOnlySession = null; 179 | } 180 | 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /src/SparkSense/StatementCompletion/CompletionSets/CompletionSetFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Media.Imaging; 3 | using Microsoft.VisualStudio.Language.Intellisense; 4 | using Microsoft.VisualStudio.Text; 5 | using SparkSense.Parser; 6 | using SparkSense.Parsing; 7 | using Spark.Parser.Markup; 8 | using System.Collections.Generic; 9 | 10 | namespace SparkSense.StatementCompletion.CompletionSets 11 | { 12 | public abstract class CompletionSetFactory : CompletionSet 13 | { 14 | protected static SnapshotPoint _triggerPoint; 15 | protected static IViewExplorer _viewExplorer; 16 | protected static CompletionBuilder _completionBuilder; 17 | 18 | internal CompletionSetFactory() : base("Spark", "Spark", null, null, null) { } 19 | 20 | protected static Node CurrentNode 21 | { 22 | get { return _triggerPoint != null ? SparkSyntax.ParseNode(CurrentContent, _triggerPoint) : null; } 23 | } 24 | protected static Type CurrentContext 25 | { 26 | get { return _triggerPoint != null ? SparkSyntax.ParseContext(CurrentContent, _triggerPoint) : null; } 27 | } 28 | protected static string CurrentContent 29 | { 30 | get { return _triggerPoint != null ? _triggerPoint.Snapshot.GetText() : string.Empty; } 31 | } 32 | public override IList Completions 33 | { 34 | get 35 | { 36 | //TODO: Rob G This is a general catch all trap because if something goes wrong during the Beta. 37 | // We don't was Visual Studio to explode, but rather just that intellisense stops working for 38 | // this particular key press - it'll try again next time. The Beta will drive out most syntax issues. 39 | try 40 | { 41 | return GetCompletionSetForNodeAndContext(); 42 | } 43 | catch 44 | { 45 | return new List(); 46 | } 47 | } 48 | } 49 | 50 | public static CompletionSet Create(SnapshotPoint triggerPoint, ITrackingSpan trackingSpan, IViewExplorer viewExplorer) where T : CompletionSetFactory, new() 51 | { 52 | _triggerPoint = triggerPoint; 53 | _viewExplorer = viewExplorer; 54 | _completionBuilder = new CompletionBuilder(_viewExplorer); 55 | return new T { ApplicableTo = trackingSpan }; 56 | } 57 | 58 | public static CompletionSet GetCompletionSetFor(SnapshotPoint triggerPoint, ITrackingSpan trackingSpan, IViewExplorer viewExplorer) 59 | { 60 | Type currentContext = SparkSyntax.ParseContext(triggerPoint.Snapshot.GetText(), triggerPoint); 61 | 62 | if (currentContext == typeof(ElementNode)) 63 | return Create(triggerPoint, trackingSpan, viewExplorer); 64 | if (currentContext == typeof(AttributeNode)) 65 | return Create(triggerPoint, trackingSpan, viewExplorer); 66 | if (currentContext == typeof(ExpressionNode)) 67 | return Create(triggerPoint, trackingSpan, viewExplorer); 68 | return null; 69 | } 70 | 71 | protected static BitmapImage GetIcon(string iconName) 72 | { 73 | BitmapImage icon; 74 | try 75 | { 76 | icon = new BitmapImage(new Uri(String.Format("pack://application:,,,/SparkSense;component/Resources/{0}.png", iconName), UriKind.Absolute)); 77 | } 78 | catch (UriFormatException ex) 79 | { 80 | icon = new BitmapImage(); 81 | } 82 | return icon; 83 | } 84 | 85 | protected abstract IList GetCompletionSetForNodeAndContext(); 86 | } 87 | } -------------------------------------------------------------------------------- /src/SparkSense/StatementCompletion/CompletionSets/ElementCompletionSet.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Microsoft.VisualStudio.Language.Intellisense; 4 | using Spark.Compiler.NodeVisitors; 5 | using SparkSense.Parsing; 6 | 7 | namespace SparkSense.StatementCompletion.CompletionSets 8 | { 9 | public class ElementCompletionSet : CompletionSetFactory 10 | { 11 | private static List _specialNodeCompletions; 12 | private List _completionList; 13 | 14 | protected override IList GetCompletionSetForNodeAndContext() 15 | { 16 | if (_completionList != null) 17 | return _completionList; 18 | _completionList = new List(); 19 | _completionList.AddRange(GetSpecialNodes()); 20 | _completionList.AddRange(GetRelatedPartials()); 21 | return _completionList.SortAlphabetically(); 22 | } 23 | 24 | private List GetSpecialNodes() 25 | { 26 | if (_specialNodeCompletions != null) return _specialNodeCompletions; 27 | 28 | var chunkBuilder = new ChunkBuilderVisitor(new VisitorContext()); 29 | var specialNodes = chunkBuilder.SpecialNodeMap.Keys; 30 | _specialNodeCompletions = new List(); 31 | 32 | foreach (var nodeName in specialNodes) 33 | _specialNodeCompletions.Add(new Completion(nodeName, nodeName, String.Format("Spark element: '{0}'", nodeName), GetIcon(Constants.ICON_SparkElement), null)); 34 | 35 | return _specialNodeCompletions; 36 | } 37 | 38 | private IEnumerable GetRelatedPartials() 39 | { 40 | var relatedPartials = new List(); 41 | if (_viewExplorer != null) 42 | foreach (var partialName in _viewExplorer.GetRelatedPartials()) 43 | relatedPartials.Add(new Completion(partialName, partialName, string.Format("Related Partial: '{0}'", partialName), GetIcon(Constants.ICON_SparkPartial), null)); 44 | 45 | return relatedPartials; 46 | } 47 | 48 | } 49 | } -------------------------------------------------------------------------------- /src/SparkSense/StatementCompletion/CompletionSets/ExpressionCompletionSet.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using Microsoft.VisualStudio.Language.Intellisense; 4 | using System; 5 | using Spark.Parser.Markup; 6 | using SparkSense.Parser; 7 | using SparkSense.Parsing; 8 | 9 | namespace SparkSense.StatementCompletion.CompletionSets 10 | { 11 | public enum ExpressionContexts { None, New, Dig } 12 | 13 | 14 | public class ExpressionCompletionSet : CompletionSetFactory 15 | { 16 | private List _completionList; 17 | 18 | public ExpressionContexts ExpressionContext 19 | { 20 | get 21 | { 22 | if (!SparkSyntax.IsExpression(CurrentContent, _triggerPoint)) 23 | return ExpressionContexts.None; 24 | 25 | if (CurrentContent[_triggerPoint - 1] == Constants.PERIOD) 26 | return ExpressionContexts.Dig; 27 | return ExpressionContexts.New; 28 | 29 | } 30 | } 31 | 32 | protected override IList GetCompletionSetForNodeAndContext() 33 | { 34 | if (_completionList != null) return _completionList; 35 | _completionList = new List(); 36 | 37 | switch (ExpressionContext) 38 | { 39 | case ExpressionContexts.New: 40 | _completionList.AddRange(GetVariables()); 41 | _completionList.AddRange(GetMembers()); 42 | break; 43 | case ExpressionContexts.Dig: 44 | _completionList.AddRange(GetMembers()); 45 | break; 46 | case ExpressionContexts.None: 47 | default: 48 | break; 49 | } 50 | return _completionList.SortAlphabetically(); 51 | } 52 | 53 | private IEnumerable GetVariables() 54 | { 55 | var variables = new List(); 56 | if (_viewExplorer == null) return variables; 57 | 58 | _viewExplorer.GetGlobalVariables().ToList().ForEach( 59 | variable => variables.Add( 60 | new Completion(variable, variable, string.Format("Global Variable: '{0}'", variable), GetIcon(Constants.ICON_SparkGlobalVariable), null))); 61 | 62 | _viewExplorer.GetLocalVariables().ToList().ForEach( 63 | variable => variables.Add( 64 | new Completion(variable, variable, string.Format("Local Variable: '{0}'", variable), GetIcon(Constants.ICON_SparkLocalVariable), null))); 65 | 66 | _viewExplorer.GetLocalMacros().ToList().ForEach( 67 | variable => variables.Add( 68 | new Completion(variable, variable, string.Format("Local Macro: '{0}'", variable), GetIcon(Constants.ICON_SparkMacro), null))); 69 | 70 | return variables; 71 | } 72 | private IEnumerable GetMembers() 73 | { 74 | var members = new List(); 75 | if (_completionBuilder == null) return members; 76 | var expression = CurrentNode as ExpressionNode; 77 | if (expression != null) 78 | { 79 | string codeSnippit = expression.Code.ToString().Trim(); 80 | return _completionBuilder.ToCompletionList(codeSnippit); 81 | } 82 | return members; 83 | } 84 | } 85 | } -------------------------------------------------------------------------------- /src/SparkSense/StatementCompletion/CompletionSource.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.Language.Intellisense; 2 | using Microsoft.VisualStudio.Text; 3 | using Spark.Parser.Markup; 4 | using SparkSense.Parsing; 5 | using SparkSense.StatementCompletion.CompletionSets; 6 | using System; 7 | using System.Collections.Generic; 8 | 9 | namespace SparkSense.StatementCompletion 10 | { 11 | public class CompletionSource : ICompletionSource 12 | { 13 | private bool _isDisposed; 14 | private ITextBuffer _textBuffer; 15 | private IProjectExplorer _projectExplorer; 16 | private IViewExplorer _viewExplorer; 17 | private ITrackingSpan _trackingSpan; 18 | 19 | public CompletionSource(ITextBuffer textBuffer, IProjectExplorer projectExplorer) 20 | { 21 | _textBuffer = textBuffer; 22 | _projectExplorer = projectExplorer; 23 | _viewExplorer = _projectExplorer.GetViewExplorer(textBuffer); 24 | _textBuffer.Changed += TextBuffer_Changed; 25 | } 26 | 27 | void TextBuffer_Changed(object sender, TextContentChangedEventArgs e) 28 | { 29 | if (e.After != _textBuffer.CurrentSnapshot) 30 | return; 31 | _viewExplorer.InvalidateView(_textBuffer.CurrentSnapshot.GetText()); 32 | } 33 | 34 | #region ICompletionSource Members 35 | 36 | public void AugmentCompletionSession(ICompletionSession session, IList completionSets) 37 | { 38 | var triggerPoint = session.GetTriggerPoint(_textBuffer).GetPoint(_textBuffer.CurrentSnapshot); 39 | 40 | if (!session.Properties.TryGetProperty(typeof(ITrackingSpan), out _trackingSpan)) 41 | _trackingSpan = triggerPoint.Snapshot.CreateTrackingSpan(new Span(triggerPoint, 0), SpanTrackingMode.EdgeInclusive); 42 | 43 | CompletionSet sparkCompletions = CompletionSetFactory.GetCompletionSetFor(triggerPoint, _trackingSpan, _viewExplorer); 44 | if (sparkCompletions == null) return; 45 | 46 | MergeSparkWithAllCompletionsSet(completionSets, sparkCompletions); 47 | completionSets.Add(sparkCompletions); 48 | 49 | session.Committed += session_Committed; 50 | } 51 | 52 | public void Dispose() 53 | { 54 | if (_isDisposed) return; 55 | GC.SuppressFinalize(this); 56 | _isDisposed = true; 57 | } 58 | 59 | #endregion 60 | 61 | private static void MergeSparkWithAllCompletionsSet(IList completionSets, CompletionSet sparkCompletions) 62 | { 63 | 64 | CompletionSet allCompletionsSet; 65 | if (!TryExtractAllCompletionsSet(completionSets, out allCompletionsSet)) return; 66 | 67 | var mergedCompletionSet = new CompletionSet( 68 | allCompletionsSet.Moniker, 69 | allCompletionsSet.DisplayName, 70 | allCompletionsSet.ApplicableTo, 71 | GetCombinedSortedList(sparkCompletions, allCompletionsSet), 72 | allCompletionsSet.CompletionBuilders); 73 | 74 | completionSets.Remove(allCompletionsSet); 75 | completionSets.Add(mergedCompletionSet); 76 | } 77 | 78 | private static bool TryExtractAllCompletionsSet(IList completionSets, out CompletionSet allCompletions) 79 | { 80 | allCompletions = null; 81 | foreach (var completionSet in completionSets) 82 | { 83 | if (completionSet.DisplayName != "All") continue; 84 | allCompletions = completionSet; 85 | return true; 86 | } 87 | return false; 88 | } 89 | 90 | private static List GetCombinedSortedList(CompletionSet sparkCompletions, CompletionSet allCompletionsSet) 91 | { 92 | var combinedList = new List(); 93 | combinedList.AddRange(allCompletionsSet.Completions); 94 | combinedList.AddRange(sparkCompletions.Completions); 95 | return combinedList.SortAlphabetically(); 96 | } 97 | 98 | private bool IsCompletionChar(ICompletionSession session, char completionChar) 99 | { 100 | var point = session.TextView.Caret.Position.BufferPosition; 101 | return point.Position > 1 && (point - 1).GetChar() == completionChar; 102 | } 103 | 104 | void session_Committed(object sender, EventArgs e) 105 | { 106 | var session = sender as ICompletionSession; 107 | if (session == null || session.IsDismissed) return; 108 | if (!IsCompletionChar(session, Constants.DOUBLE_QUOTE) 109 | && !IsCompletionChar(session, Constants.SINGLE_QUOTE)) return; 110 | 111 | session.TextView.Caret.MoveToPreviousCaretPosition(); 112 | } 113 | 114 | } 115 | } -------------------------------------------------------------------------------- /src/SparkSense/StatementCompletion/KeyPressInterceptor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio; 3 | using Microsoft.VisualStudio.OLE.Interop; 4 | using Microsoft.VisualStudio.TextManager.Interop; 5 | 6 | namespace SparkSense.StatementCompletion 7 | { 8 | internal class KeyPressInterceptor : IOleCommandTarget 9 | { 10 | private readonly IVsTextView _textViewAdapter; 11 | private readonly CompletionSessionManager _sessionManager; 12 | private IOleCommandTarget _nextCommand; 13 | 14 | public KeyPressInterceptor(ViewCreationListener createdView) 15 | { 16 | _textViewAdapter = createdView.TextViewAdapter; 17 | var textNavigator = createdView.TextNavigator.GetTextStructureNavigator(createdView.TextView.TextBuffer); 18 | _sessionManager = new CompletionSessionManager(createdView.CompletionBroker, createdView.TextView, textNavigator); 19 | 20 | TryChainTheNextCommand(); 21 | } 22 | 23 | private void TryChainTheNextCommand() 24 | { 25 | if (_textViewAdapter != null) _textViewAdapter.AddCommandFilter(this, out _nextCommand); 26 | } 27 | 28 | #region IOleCommandTarget Members 29 | 30 | public int QueryStatus(ref Guid cmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText) 31 | { 32 | return _nextCommand.QueryStatus(ref cmdGroup, cCmds, prgCmds, pCmdText); 33 | } 34 | 35 | public int Exec(ref Guid cmdGroup, uint key, uint cmdExecOpt, IntPtr pvaIn, IntPtr pvaOut) 36 | { 37 | char inputCharacter = key.GetInputCharacter(cmdGroup, pvaIn); 38 | 39 | if (_sessionManager.IsCompletionCommitted(key, inputCharacter)) return VSConstants.S_OK; 40 | 41 | int keyPressResult = _nextCommand.Exec(ref cmdGroup, key, cmdExecOpt, pvaIn, pvaOut); 42 | return _sessionManager.IsCompletionStarted(key, inputCharacter) ? VSConstants.S_OK : keyPressResult; 43 | } 44 | 45 | #endregion 46 | } 47 | } -------------------------------------------------------------------------------- /src/SparkSense/StatementCompletion/ViewCreationListener.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.Composition; 3 | using Microsoft.VisualStudio.Editor; 4 | using Microsoft.VisualStudio.Language.Intellisense; 5 | using Microsoft.VisualStudio.Text.Editor; 6 | using Microsoft.VisualStudio.TextManager.Interop; 7 | using Microsoft.VisualStudio.Utilities; 8 | using Microsoft.VisualStudio.Text.Operations; 9 | 10 | namespace SparkSense.StatementCompletion 11 | { 12 | [Export(typeof(IVsTextViewCreationListener))] 13 | [Name("Spark View Creation Listener")] 14 | [ContentType("spark")] 15 | [ContentType("HTML")] 16 | [TextViewRole(PredefinedTextViewRoles.Editable)] 17 | public class ViewCreationListener : IVsTextViewCreationListener 18 | { 19 | [Import] 20 | public IVsEditorAdaptersFactoryService AdaptersFactoryService; 21 | 22 | [Import] 23 | public ICompletionBroker CompletionBroker; 24 | 25 | [Import] 26 | public ISparkServiceProvider ServiceProvider { get; set; } 27 | 28 | [Import] 29 | public ITextStructureNavigatorSelectorService TextNavigator { get; set; } 30 | 31 | public IVsTextView TextViewAdapter { get; private set; } 32 | public IWpfTextView TextView { get; private set; } 33 | 34 | #region IVsTextViewCreationListener Members 35 | 36 | public void VsTextViewCreated(IVsTextView textViewAdapter) 37 | { 38 | TextViewAdapter = textViewAdapter; 39 | if (!TryGetTextView()) return; 40 | 41 | InitTypes(); 42 | 43 | Func interceptionCreator = () => new KeyPressInterceptor(this); 44 | 45 | TextView.Properties.GetOrCreateSingletonProperty(interceptionCreator); 46 | } 47 | 48 | private void InitTypes() 49 | { 50 | if (ServiceProvider != null) 51 | { 52 | if (ServiceProvider.ProjectExplorer != null) 53 | { 54 | var types = ServiceProvider.ProjectExplorer.GetProjectReferencedTypes(); 55 | } 56 | } 57 | } 58 | 59 | private bool TryGetTextView() 60 | { 61 | if (AdaptersFactoryService == null) return false; 62 | TextView = AdaptersFactoryService.GetWpfTextView(TextViewAdapter); 63 | return TextView != null; 64 | } 65 | #endregion 66 | } 67 | } -------------------------------------------------------------------------------- /src/SparkSense/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/SparkSense/source.extension.vsixmanifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | SparkSense 5 | Robert Greyling 6 | 0.5 7 | This is a Spark extension to the Visual Studio 2010 Editor. 8 | 1033 9 | http://blog.robertgreyling.com 10 | license.txt 11 | SparkIcon.png 12 | SparkLogo.png 13 | 14 | 15 | Ultimate 16 | Premium 17 | Pro 18 | 19 | 20 | 21 | 22 | 23 | 24 | |%CurrentProject%| 25 | ItemTemplates 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/packages/NUnit.2.6.1/NUnit.2.6.1.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SparkViewEngine/SparkSense/08c46f516a03d7276350c1cf7ceea043673008a6/src/packages/NUnit.2.6.1/NUnit.2.6.1.nupkg -------------------------------------------------------------------------------- /src/packages/NUnit.2.6.1/lib/nunit.framework.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SparkViewEngine/SparkSense/08c46f516a03d7276350c1cf7ceea043673008a6/src/packages/NUnit.2.6.1/lib/nunit.framework.dll -------------------------------------------------------------------------------- /src/packages/NUnit.2.6.1/license.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SparkViewEngine/SparkSense/08c46f516a03d7276350c1cf7ceea043673008a6/src/packages/NUnit.2.6.1/license.txt -------------------------------------------------------------------------------- /src/packages/RhinoMocks.3.6.1/RhinoMocks.3.6.1.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SparkViewEngine/SparkSense/08c46f516a03d7276350c1cf7ceea043673008a6/src/packages/RhinoMocks.3.6.1/RhinoMocks.3.6.1.nupkg -------------------------------------------------------------------------------- /src/packages/RhinoMocks.3.6.1/lib/net/Rhino.Mocks.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SparkViewEngine/SparkSense/08c46f516a03d7276350c1cf7ceea043673008a6/src/packages/RhinoMocks.3.6.1/lib/net/Rhino.Mocks.dll -------------------------------------------------------------------------------- /src/packages/Spark.1.7.2.0/Spark.1.7.2.0.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SparkViewEngine/SparkSense/08c46f516a03d7276350c1cf7ceea043673008a6/src/packages/Spark.1.7.2.0/Spark.1.7.2.0.nupkg -------------------------------------------------------------------------------- /src/packages/Spark.1.7.2.0/lib/NET35/Spark.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SparkViewEngine/SparkSense/08c46f516a03d7276350c1cf7ceea043673008a6/src/packages/Spark.1.7.2.0/lib/NET35/Spark.dll -------------------------------------------------------------------------------- /src/packages/Spark.1.7.2.0/lib/NET40/Spark.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SparkViewEngine/SparkSense/08c46f516a03d7276350c1cf7ceea043673008a6/src/packages/Spark.1.7.2.0/lib/NET40/Spark.dll -------------------------------------------------------------------------------- /src/packages/fasterflect.2.1.0/fasterflect.2.1.0.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SparkViewEngine/SparkSense/08c46f516a03d7276350c1cf7ceea043673008a6/src/packages/fasterflect.2.1.0/fasterflect.2.1.0.nupkg -------------------------------------------------------------------------------- /src/packages/fasterflect.2.1.0/lib/net35/Fasterflect.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SparkViewEngine/SparkSense/08c46f516a03d7276350c1cf7ceea043673008a6/src/packages/fasterflect.2.1.0/lib/net35/Fasterflect.dll -------------------------------------------------------------------------------- /src/packages/fasterflect.2.1.0/lib/net40/Fasterflect.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SparkViewEngine/SparkSense/08c46f516a03d7276350c1cf7ceea043673008a6/src/packages/fasterflect.2.1.0/lib/net40/Fasterflect.dll -------------------------------------------------------------------------------- /src/packages/repositories.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | --------------------------------------------------------------------------------