Skip to content

Commit cf2f3c3

Browse files
committed
Add the PowerShell documentation Class samples
1 parent 23ec46b commit cf2f3c3

File tree

2 files changed

+282
-1
lines changed

2 files changed

+282
-1
lines changed

PowerShell.sublime-syntax

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ contexts:
219219
commands-reserved:
220220
# Builtin cmdlets with reserved verbs
221221
- match: \b(?i:(?:ForEach|Where|Sort|Tee)-Object)\b
222-
scope: support.function.powershell
222+
scope: meta.function-call.powershell support.function.powershell
223223

224224
script-invocation:
225225
- match: \b[\w.\\/-]+\.(?i:exe|com|cmd|bat|ps1)\b

Tests/syntax_test_Class.ps1

Lines changed: 281 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,3 +136,284 @@ class TypeName
136136

137137
$object.MemberMethod2()
138138
# @@@@@@@@@@@@@ reference
139+
140+
141+
# PowerShell documentation examples
142+
# https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_classes
143+
144+
# Example 1 - Minimal definition
145+
class Device {
146+
# @@@@@@ definition
147+
[string]$Brand
148+
}
149+
150+
$dev = [Device]::new()
151+
# @@@ reference
152+
$dev.Brand = "Fabrikam, Inc."
153+
$dev
154+
155+
156+
# Example 2 - Class with instance members
157+
class Book {
158+
# @@@@ definition
159+
# Class properties
160+
[string] $Title
161+
[string] $Author
162+
[string] $Synopsis
163+
[string] $Publisher
164+
[datetime] $PublishDate
165+
[int] $PageCount
166+
[string[]] $Tags
167+
# Default constructor
168+
Book() { $this.Init(@{}) }
169+
# @@@@ reference
170+
# Convenience constructor from hashtable
171+
Book([hashtable]$Properties) { $this.Init($Properties) }
172+
# @@@@ reference
173+
# Common constructor for title and author
174+
Book([string]$Title, [string]$Author) {
175+
$this.Init(@{Title = $Title; Author = $Author })
176+
# @@@@ reference
177+
}
178+
# Shared initializer method
179+
[void] Init([hashtable]$Properties) {
180+
# @@@@ definition
181+
foreach ($Property in $Properties.Keys) {
182+
$this.$Property = $Properties.$Property
183+
}
184+
}
185+
# Method to calculate reading time as 2 minutes per page
186+
[timespan] GetReadingTime() {
187+
# @@@@@@@@@@@@@@ definition
188+
if ($this.PageCount -le 0) {
189+
throw 'Unable to determine reading time from page count.'
190+
}
191+
$Minutes = $this.PageCount * 2
192+
return [timespan]::new(0, $Minutes, 0)
193+
# @@@ reference
194+
}
195+
# Method to calculate how long ago a book was published
196+
[timespan] GetPublishedAge() {
197+
# @@@@@@@@@@@@@@@ definition
198+
if (
199+
$null -eq $this.PublishDate -or
200+
$this.PublishDate -eq [datetime]::MinValue
201+
) { throw 'PublishDate not defined' }
202+
203+
return (Get-Date) - $this.PublishDate
204+
# @@@@@@@@ reference
205+
}
206+
# Method to return a string representation of the book
207+
[string] ToString() {
208+
# @@@@@@@@ definition
209+
return "$($this.Title) by $($this.Author) ($($this.PublishDate.Year))"
210+
}
211+
}
212+
213+
[BookList]::Add([Book]::new(@{
214+
# @@@ reference
215+
# @@@ reference
216+
Title = 'The Fellowship of the Ring'
217+
Author = 'J.R.R. Tolkien'
218+
Publisher = 'George Allen & Unwin'
219+
PublishDate = '1954-07-29'
220+
PageCount = 423
221+
Tags = @('Fantasy', 'Adventure')
222+
}))
223+
224+
[BookList]::Find({
225+
# @@@@ reference
226+
param ($b)
227+
228+
$b.PublishDate -gt '1950-01-01'
229+
}).Title
230+
231+
[BookList]::FindAll({
232+
# @@@@@@@ reference
233+
param($b)
234+
235+
$b.Author -match 'Tolkien'
236+
}).Title
237+
238+
[BookList]::Remove($Book)
239+
# @@@@@@ reference
240+
[BookList]::Books.Title
241+
242+
[BookList]::RemoveBy('Author', 'J.R.R. Tolkien')
243+
# @@@@@@@@ reference
244+
"Titles: $([BookList]::Books.Title)"
245+
246+
[BookList]::Add($Book)
247+
# @@@ reference
248+
[BookList]::Add($Book)
249+
# @@@ reference
250+
251+
252+
# Example 3 - Class with static members
253+
class BookList {
254+
# @@@@@@@@ definition
255+
# Static property to hold the list of books
256+
static [System.Collections.Generic.List[Book]] $Books
257+
# Static method to initialize the list of books. Called in the other
258+
# static methods to avoid needing to explicit initialize the value.
259+
static [void] Initialize() { [BookList]::Initialize($false) }
260+
# @@@@@@@@@@ definition
261+
# @@@@@@@@@@ reference
262+
static [bool] Initialize([bool]$Force) {
263+
# @@@@@@@@@@ definition
264+
if ([BookList]::Books.Count -gt 0 -and -not $Force) {
265+
return $false
266+
}
267+
268+
[BookList]::Books = [System.Collections.Generic.List[Book]]::new()
269+
# @@@ reference
270+
271+
return $true
272+
}
273+
# Ensure a book is valid for the list.
274+
static [void] Validate([book]$Book) {
275+
# @@@@@@@@ definition
276+
$Prefix = @(
277+
'Book validation failed: Book must be defined with the Title,'
278+
'Author, and PublishDate properties, but'
279+
) -join ' '
280+
if ($null -eq $Book) { throw "$Prefix was null" }
281+
if ([string]::IsNullOrEmpty($Book.Title)) {
282+
# @@@@@@@@@@@@@ reference
283+
throw "$Prefix Title wasn't defined"
284+
}
285+
if ([string]::IsNullOrEmpty($Book.Author)) {
286+
# @@@@@@@@@@@@@ reference
287+
throw "$Prefix Author wasn't defined"
288+
}
289+
if ([datetime]::MinValue -eq $Book.PublishDate) {
290+
throw "$Prefix PublishDate wasn't defined"
291+
}
292+
}
293+
# Static methods to manage the list of books.
294+
# Add a book if it's not already in the list.
295+
static [void] Add([Book]$Book) {
296+
# @@@ definition
297+
[BookList]::Initialize()
298+
# @@@@@@@@@@ reference
299+
[BookList]::Validate($Book)
300+
# @@@@@@@@ reference
301+
if ([BookList]::Books.Contains($Book)) {
302+
# @@@@@@@@ reference
303+
throw "Book '$Book' already in list"
304+
}
305+
306+
$FindPredicate = {
307+
param([Book]$b)
308+
309+
$b.Title -eq $Book.Title -and
310+
$b.Author -eq $Book.Author -and
311+
$b.PublishDate -eq $Book.PublishDate
312+
}.GetNewClosure()
313+
if ([BookList]::Books.Find($FindPredicate)) {
314+
# @@@@ reference
315+
throw "Book '$Book' already in list"
316+
}
317+
318+
[BookList]::Books.Add($Book)
319+
# @@@ reference
320+
}
321+
# Clear the list of books.
322+
static [void] Clear() {
323+
# @@@@@ definition
324+
[BookList]::Initialize()
325+
# @@@@@@@@@@ reference
326+
[BookList]::Books.Clear()
327+
# @@@@@ reference
328+
}
329+
# Find a specific book using a filtering scriptblock.
330+
static [Book] Find([scriptblock]$Predicate) {
331+
# @@@@ definition
332+
[BookList]::Initialize()
333+
# @@@@@@@@@@ reference
334+
return [BookList]::Books.Find($Predicate)
335+
# @@@@ reference
336+
}
337+
# Find every book matching the filtering scriptblock.
338+
static [Book[]] FindAll([scriptblock]$Predicate) {
339+
[BookList]::Initialize()
340+
# @@@@@@@@@@ reference
341+
return [BookList]::Books.FindAll($Predicate)
342+
# @@@@@@@ reference
343+
}
344+
# Remove a specific book.
345+
static [void] Remove([Book]$Book) {
346+
# @@@@@@ definition
347+
[BookList]::Initialize()
348+
# @@@@@@@@@@ reference
349+
[BookList]::Books.Remove($Book)
350+
# @@@@@@ reference
351+
}
352+
# Remove a book by property value.
353+
static [void] RemoveBy([string]$Property, [string]$Value) {
354+
# @@@@@@@@ definition
355+
[BookList]::Initialize()
356+
# @@@@@@@@@@ reference
357+
$Index = [BookList]::Books.FindIndex({
358+
# @@@@@@@@@ reference
359+
param($b)
360+
$b.$Property -eq $Value
361+
}.GetNewClosure())
362+
if ($Index -ge 0) {
363+
[BookList]::Books.RemoveAt($Index)
364+
# @@@@@@@@ reference
365+
}
366+
}
367+
}
368+
369+
370+
# Example 4 - Class definition with and without Runspace affinity
371+
372+
# Class definition with Runspace affinity (default behavior)
373+
class UnsafeClass {
374+
# @@@@@@@@@@@ definition
375+
static [Object] ShowRunspaceId($Val) {
376+
# @@@@@@@@@@@@@@ definition
377+
return [pscustomobject]@{
378+
ThreadId = [Threading.Thread]::CurrentThread.ManagedThreadId
379+
RunspaceId = [runspace]::DefaultRunspace.Id
380+
}
381+
}
382+
}
383+
384+
$unsafe = [UnsafeClass]::new()
385+
# @@@ reference
386+
387+
while ($true) {
388+
1..10 | ForEach-Object -Parallel {
389+
# @@@@@@@@@@@@@@ reference
390+
Start-Sleep -ms 100
391+
# @@@@@@@@@@@ reference
392+
($Using:unsafe)::ShowRunspaceId($_)
393+
}
394+
}
395+
396+
# Class definition with NoRunspaceAffinity attribute
397+
[NoRunspaceAffinity()]
398+
class SafeClass {
399+
# @@@@@@@@@ definition
400+
static [Object] ShowRunspaceId($Val) {
401+
# @@@@@@@@@@@@@@ definition
402+
return [pscustomobject]@{
403+
ThreadId = [Threading.Thread]::CurrentThread.ManagedThreadId
404+
RunspaceId = [runspace]::DefaultRunspace.Id
405+
}
406+
}
407+
}
408+
409+
$safe = [SafeClass]::new()
410+
# @@@ reference
411+
412+
while ($true) {
413+
1..10 | ForEach-Object -Parallel {
414+
# @@@@@@@@@@@@@@ reference
415+
Start-Sleep -ms 100
416+
# @@@@@@@@@@@ reference
417+
($Using:safe)::ShowRunspaceId($_)
418+
}
419+
}

0 commit comments

Comments
 (0)