Skip to content

Commit a1e6dbc

Browse files
committed
Merge pull request #183 from PowerShell/daviwil/using-module-fix
Fix #99: 'using module' relative path resolution
2 parents 5e88358 + 8d2f984 commit a1e6dbc

File tree

13 files changed

+141
-29
lines changed

13 files changed

+141
-29
lines changed

appveyor.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
version: '$(core_version).{build}'
2-
os: Unstable
2+
os: WMF 5
33
configuration: Release
44
clone_depth: 10
55

src/PowerShellEditorServices/PowerShellEditorServices.csproj

+10-3
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,16 @@
1313
<FileAlignment>512</FileAlignment>
1414
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
1515
<RestorePackages>true</RestorePackages>
16-
<DefineConstants Condition=" '$(PowerShellVersion)' == 'v3'">PowerShellv3</DefineConstants>
17-
<DefineConstants Condition=" '$(PowerShellVersion)' == 'v4'">PowerShellv4</DefineConstants>
18-
<DefineConstants Condition=" '$(PowerShellVersion)' == '' Or '$(PowerShellVersion)' == 'v5'">PowerShellv5</DefineConstants>
16+
<DefineConstants Condition="'$(PowerShellVersion)' == 'v3'">$(DefineConstants);PowerShellv3</DefineConstants>
17+
<DefineConstants Condition="'$(PowerShellVersion)' == 'v4'">$(DefineConstants);PowerShellv4</DefineConstants>
18+
<!-- NOTE: -->
19+
<!-- For PowerShell v5 there are some differences between the APIs released with -->
20+
<!-- Windows 10 RTM and Windows 10 Update 1, thus we need to distinguish between -->
21+
<!-- the two in our code. v5r1 indicates Win 10 RTM (10240) and v5r2 indicates -->
22+
<!-- Win10 Update 1 (10586). The PowerShellv5 constant will be defined for both -->
23+
<!-- of these versions for anything that should work against both APIs. -->
24+
<DefineConstants Condition="'$(PowerShellVersion)' == 'v5r1'">$(DefineConstants);PowerShellv5r1;PowerShellv5</DefineConstants>
25+
<DefineConstants Condition="'$(PowerShellVersion)' == 'v5r2' Or '$(PowerShellVersion)' == ''">$(DefineConstants);PowerShellv5r2;PowerShellv5</DefineConstants>
1926
</PropertyGroup>
2027
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
2128
<DebugSymbols>true</DebugSymbols>

src/PowerShellEditorServices/Session/EditorSession.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,6 @@ public class EditorSession
6060
/// </summary>
6161
public void StartSession()
6262
{
63-
// Create a workspace to contain open files
64-
this.Workspace = new Workspace();
65-
6663
// Initialize all services
6764
this.PowerShellContext = new PowerShellContext();
6865
this.LanguageService = new LanguageService(this.PowerShellContext);
@@ -81,6 +78,9 @@ public void StartSession()
8178
LogLevel.Warning,
8279
"Script Analyzer binaries not found, AnalysisService will be disabled.");
8380
}
81+
82+
// Create a workspace to contain open files
83+
this.Workspace = new Workspace(this.PowerShellContext.PowerShellVersion);
8484
}
8585

8686
#endregion

src/PowerShellEditorServices/Workspace/ScriptFile.cs

+43-6
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ public class ScriptFile
2121
#region Private Fields
2222

2323
private Token[] scriptTokens;
24+
private Version powerShellVersion;
2425

2526
#endregion
2627

@@ -126,12 +127,18 @@ public string[] ReferencedFiles
126127
/// <param name="filePath">The path at which the script file resides.</param>
127128
/// <param name="clientFilePath">The path which the client uses to identify the file.</param>
128129
/// <param name="textReader">The TextReader to use for reading the file's contents.</param>
129-
public ScriptFile(string filePath, string clientFilePath, TextReader textReader)
130+
/// <param name="powerShellVersion">The version of PowerShell for which the script is being parsed.</param>
131+
public ScriptFile(
132+
string filePath,
133+
string clientFilePath,
134+
TextReader textReader,
135+
Version powerShellVersion)
130136
{
131137
this.FilePath = filePath;
132138
this.ClientFilePath = clientFilePath;
133139
this.IsAnalysisEnabled = true;
134140
this.IsInMemory = Workspace.IsPathInMemory(filePath);
141+
this.powerShellVersion = powerShellVersion;
135142

136143
this.SetFileContents(textReader.ReadToEnd());
137144
}
@@ -142,11 +149,17 @@ public ScriptFile(string filePath, string clientFilePath, TextReader textReader)
142149
/// <param name="filePath">The path at which the script file resides.</param>
143150
/// <param name="clientFilePath">The path which the client uses to identify the file.</param>
144151
/// <param name="initialBuffer">The initial contents of the script file.</param>
145-
public ScriptFile(string filePath, string clientFilePath, string initialBuffer)
152+
/// <param name="powerShellVersion">The version of PowerShell for which the script is being parsed.</param>
153+
public ScriptFile(
154+
string filePath,
155+
string clientFilePath,
156+
string initialBuffer,
157+
Version powerShellVersion)
146158
{
147159
this.FilePath = filePath;
148160
this.ClientFilePath = clientFilePath;
149161
this.IsAnalysisEnabled = true;
162+
this.powerShellVersion = powerShellVersion;
150163

151164
this.SetFileContents(initialBuffer);
152165
}
@@ -358,15 +371,39 @@ private void ParseFileContents()
358371

359372
try
360373
{
374+
#if PowerShellv5r2
375+
// This overload appeared with Windows 10 Update 1
376+
if (this.powerShellVersion.Major >= 5 &&
377+
this.powerShellVersion.Build >= 10586)
378+
{
379+
// Include the file path so that module relative
380+
// paths are evaluated correctly
381+
this.ScriptAst =
382+
Parser.ParseInput(
383+
this.Contents,
384+
this.FilePath,
385+
out this.scriptTokens,
386+
out parseErrors);
387+
}
388+
else
389+
{
390+
this.ScriptAst =
391+
Parser.ParseInput(
392+
this.Contents,
393+
out this.scriptTokens,
394+
out parseErrors);
395+
}
396+
#else
361397
this.ScriptAst =
362398
Parser.ParseInput(
363-
this.Contents,
364-
out this.scriptTokens,
399+
this.Contents,
400+
out this.scriptTokens,
365401
out parseErrors);
402+
#endif
366403
}
367404
catch (RuntimeException ex)
368405
{
369-
var parseError =
406+
var parseError =
370407
new ParseError(
371408
null,
372409
ex.ErrorRecord.FullyQualifiedErrorId,
@@ -388,6 +425,6 @@ private void ParseFileContents()
388425
AstOperations.FindDotSourcedIncludes(this.ScriptAst);
389426
}
390427

391-
#endregion
428+
#endregion
392429
}
393430
}

src/PowerShellEditorServices/Workspace/Workspace.cs

+28-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ public class Workspace
2020
{
2121
#region Private Fields
2222

23+
private Version powerShellVersion;
2324
private Dictionary<string, ScriptFile> workspaceFiles = new Dictionary<string, ScriptFile>();
2425

2526
#endregion
@@ -33,6 +34,19 @@ public class Workspace
3334

3435
#endregion
3536

37+
#region Constructors
38+
39+
/// <summary>
40+
/// Creates a new instance of the Workspace class.
41+
/// </summary>
42+
/// <param name="powerShellVersion">The version of PowerShell for which scripts will be parsed.</param>
43+
public Workspace(Version powerShellVersion)
44+
{
45+
this.powerShellVersion = powerShellVersion;
46+
}
47+
48+
#endregion
49+
3650
#region Public Methods
3751

3852
/// <summary>
@@ -63,7 +77,13 @@ public ScriptFile GetFile(string filePath)
6377

6478
using (StreamReader streamReader = new StreamReader(resolvedFilePath, Encoding.UTF8))
6579
{
66-
scriptFile = new ScriptFile(resolvedFilePath, filePath, streamReader);
80+
scriptFile =
81+
new ScriptFile(
82+
resolvedFilePath,
83+
filePath,
84+
streamReader,
85+
this.powerShellVersion);
86+
6787
this.workspaceFiles.Add(keyName, scriptFile);
6888
}
6989

@@ -92,7 +112,13 @@ public ScriptFile GetFileBuffer(string filePath, string initialBuffer)
92112
ScriptFile scriptFile = null;
93113
if (!this.workspaceFiles.TryGetValue(keyName, out scriptFile))
94114
{
95-
scriptFile = new ScriptFile(resolvedFilePath, filePath, initialBuffer);
115+
scriptFile =
116+
new ScriptFile(
117+
resolvedFilePath,
118+
filePath,
119+
initialBuffer,
120+
this.powerShellVersion);
121+
96122
this.workspaceFiles.Add(keyName, scriptFile);
97123

98124
Logger.Write(LogLevel.Verbose, "Opened file as in-memory buffer: " + resolvedFilePath);

test/PowerShellEditorServices.Test.Host/LanguageServerTests.cs

+15
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,21 @@ await this.WaitForEvent(
8181
Assert.Contains("unapproved", diagnostics.Diagnostics[0].Message);
8282
}
8383

84+
[Fact]
85+
public async Task ServiceReturnsNoErrorsForUsingRelativeModulePaths()
86+
{
87+
// Send the 'didOpen' event
88+
await this.SendOpenFileEvent("TestFiles\\Module.psm1", false);
89+
90+
// Wait for the diagnostic event
91+
PublishDiagnosticsNotification diagnostics =
92+
await this.WaitForEvent(
93+
PublishDiagnosticsNotification.Type);
94+
95+
// Was there a syntax error?
96+
Assert.Equal(0, diagnostics.Diagnostics.Length);
97+
}
98+
8499
[Fact]
85100
public async Task ServiceCompletesFunctionName()
86101
{

test/PowerShellEditorServices.Test.Host/PowerShellEditorServices.Test.Host.csproj

+6
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,18 @@
7474
<ItemGroup>
7575
<None Include="App.config" />
7676
<None Include="packages.config" />
77+
<None Include="TestFiles\ChildModule\ChildModule.psm1">
78+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
79+
</None>
7780
<None Include="TestFiles\CompleteFunctionName.ps1">
7881
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
7982
</None>
8083
<None Include="TestFiles\FindReferences.ps1">
8184
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
8285
</None>
86+
<None Include="TestFiles\Module.psm1">
87+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
88+
</None>
8389
<None Include="TestFiles\MultiLineReplace.ps1">
8490
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
8591
</None>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
function Get-Stuff {
2+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
using module ".\ChildModule"

test/PowerShellEditorServices.Test/Debugging/DebugServiceTests.cs

+9-4
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ public class DebugServiceTests : IDisposable
3030

3131
public DebugServiceTests()
3232
{
33-
this.workspace = new Workspace();
33+
this.powerShellContext = new PowerShellContext();
34+
this.powerShellContext.SessionStateChanged += powerShellContext_SessionStateChanged;
35+
36+
this.workspace = new Workspace(this.powerShellContext.PowerShellVersion);
3437

3538
// Load the test debug file
3639
this.debugScriptFile =
@@ -41,13 +44,15 @@ public DebugServiceTests()
4144
this.workspace.GetFile(
4245
@"..\..\..\PowerShellEditorServices.Test.Shared\Debugging\VariableTest.ps1");
4346

44-
this.powerShellContext = new PowerShellContext();
45-
this.powerShellContext.SessionStateChanged += powerShellContext_SessionStateChanged;
46-
4747
this.debugService = new DebugService(this.powerShellContext);
4848
this.debugService.DebuggerStopped += debugService_DebuggerStopped;
4949
this.debugService.BreakpointUpdated += debugService_BreakpointUpdated;
5050
this.runnerContext = SynchronizationContext.Current;
51+
52+
// Load the test debug file
53+
this.debugScriptFile =
54+
this.workspace.GetFile(
55+
@"..\..\..\PowerShellEditorServices.Test.Shared\Debugging\DebugTest.ps1");
5156
}
5257

5358
async void powerShellContext_SessionStateChanged(object sender, SessionStateChangedEventArgs e)

test/PowerShellEditorServices.Test/Language/LanguageServiceTests.cs

+1-2
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,8 @@ public class LanguageServiceTests : IDisposable
3232

3333
public LanguageServiceTests()
3434
{
35-
this.workspace = new Workspace();
36-
3735
this.powerShellContext = new PowerShellContext();
36+
this.workspace = new Workspace(this.powerShellContext.PowerShellVersion);
3837
this.languageService = new LanguageService(this.powerShellContext);
3938
}
4039

test/PowerShellEditorServices.Test/Language/PowerShellVersionTests.cs

+6-6
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ namespace Microsoft.PowerShell.EditorServices.Test.Language
1616
public class PowerShellVersionTests
1717
{
1818
[Theory]
19-
[InlineData("3")]
20-
[InlineData("4")]
21-
[InlineData("5")]
22-
public void CompilesWithPowerShellVersion(string version)
19+
[InlineData("3", "4")]
20+
[InlineData("4", "4")]
21+
[InlineData("5", "5r1")]
22+
public void CompilesWithPowerShellVersion(string version, string versionSuffix)
2323
{
2424
var assemblyPath =
2525
Path.GetFullPath(
@@ -40,15 +40,15 @@ public void CompilesWithPowerShellVersion(string version)
4040

4141
try
4242
{
43-
Compile(projectVersion, version);
43+
Compile(projectVersion, version, versionSuffix);
4444
}
4545
finally
4646
{
4747
File.Delete(projectVersion);
4848
}
4949
}
5050

51-
private void Compile(string project, string version)
51+
private void Compile(string project, string version, string versionSuffix)
5252
{
5353
string msbuild;
5454
using (var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\MSBuild\ToolsVersions\14.0"))

test/PowerShellEditorServices.Test/Session/ScriptFileTests.cs

+16-2
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,16 @@
44
//
55

66
using Microsoft.PowerShell.EditorServices;
7+
using System;
78
using System.IO;
89
using Xunit;
910

1011
namespace PSLanguageService.Test
1112
{
1213
public class FileChangeTests
1314
{
15+
private static readonly Version PowerShellVersion = new Version("5.0");
16+
1417
[Fact]
1518
public void CanApplySingleLineInsert()
1619
{
@@ -135,7 +138,13 @@ public void FindsDotSourcedFiles()
135138

136139
using (StringReader stringReader = new StringReader(exampleScriptContents))
137140
{
138-
ScriptFile scriptFile = new ScriptFile("DotSourceTestFile.ps1", "DotSourceTestFile.ps1", stringReader);
141+
ScriptFile scriptFile =
142+
new ScriptFile(
143+
"DotSourceTestFile.ps1",
144+
"DotSourceTestFile.ps1",
145+
stringReader,
146+
PowerShellVersion);
147+
139148
Assert.Equal(3, scriptFile.ReferencedFiles.Length);
140149
System.Console.Write("a" + scriptFile.ReferencedFiles[0]);
141150
Assert.Equal(@".\athing.ps1", scriptFile.ReferencedFiles[0]);
@@ -150,7 +159,12 @@ private void AssertFileChange(
150159
using (StringReader stringReader = new StringReader(initialString))
151160
{
152161
// Create an in-memory file from the StringReader
153-
ScriptFile fileToChange = new ScriptFile("TestFile.ps1", "TestFile.ps1", stringReader);
162+
ScriptFile fileToChange =
163+
new ScriptFile(
164+
"TestFile.ps1",
165+
"TestFile.ps1",
166+
stringReader,
167+
PowerShellVersion);
154168

155169
// Apply the FileChange and assert the resulting contents
156170
fileToChange.ApplyChange(fileChange);

0 commit comments

Comments
 (0)