diff --git a/Sources/SwiftRefactor/SyntaxUtils.swift b/Sources/SwiftRefactor/SyntaxUtils.swift
index 62a108c325c..d8ebdc3099e 100644
--- a/Sources/SwiftRefactor/SyntaxUtils.swift
+++ b/Sources/SwiftRefactor/SyntaxUtils.swift
@@ -31,13 +31,3 @@ extension Trivia {
     return Trivia(pieces: self.reversed().drop(while: \.isWhitespace).reversed())
   }
 }
-
-extension TypeSyntax {
-  var isVoid: Bool {
-    switch self.as(TypeSyntaxEnum.self) {
-    case .identifierType(let identifierType) where identifierType.name.text == "Void": return true
-    case .tupleType(let tupleType) where tupleType.elements.isEmpty: return true
-    default: return false
-    }
-  }
-}
diff --git a/Sources/SwiftSyntax/Utils.swift b/Sources/SwiftSyntax/Utils.swift
index 3be00281ca9..a2a507ee969 100644
--- a/Sources/SwiftSyntax/Utils.swift
+++ b/Sources/SwiftSyntax/Utils.swift
@@ -102,3 +102,65 @@ extension RawUnexpectedNodesSyntax {
     self.init(raw: raw)
   }
 }
+
+extension TypeSyntaxProtocol {
+  /// Check if this syntax matches any of the standard names for `Void`:
+  /// * Void
+  /// * Swift.Void
+  /// * ()
+  public var isVoid: Bool {
+    if let identifierType = self.as(IdentifierTypeSyntax.self) {
+      return identifierType.name.text == "Void"
+    }
+    if let memberType = self.as(MemberTypeSyntax.self) {
+      return memberType.baseType.isSwiftCoreModule && memberType.name.text == "Void"
+    }
+    if let tupleType = self.as(TupleTypeSyntax.self) {
+      return tupleType.elements.isEmpty
+    }
+    return false
+  }
+
+  var isSwiftCoreModule: Bool {
+    guard let identifierType = self.as(IdentifierTypeSyntax.self) else {
+      return false
+    }
+    return identifierType.name.text == "Swift"
+  }
+
+  /// Check if this syntax could resolve to the type passed. Only supports types where the canonical type
+  /// can be named using only IdentifierTypeSyntax and MemberTypeSyntax. A non-exhaustive list of unsupported
+  /// types includes:
+  /// * array types
+  /// * function types
+  /// * optional types
+  /// * tuple types (including Void!)
+  /// The type syntax is allowed to use any level of qualified name for the type, e.g. Swift.Int.self
+  /// will match against both "Swift.Int" and "Int".
+  ///
+  /// - Parameter type: Type to check against. NB: if passing a type alias, the canonical type will be used.
+  /// - Returns: true if `self` spells out some suffix of the fully qualified name of `type`, otherwise false
+  public func canRepresentBasicType(type: Any.Type) -> Bool {
+    let qualifiedTypeName = String(reflecting: type)
+    var typeNames = qualifiedTypeName.split(separator: ".")
+    var currType: TypeSyntaxProtocol = self
+
+    while !typeNames.isEmpty {
+      let typeName = typeNames.popLast()!
+      if let identifierType = currType.as(IdentifierTypeSyntax.self) {
+        // It doesn't matter whether this is the final element of typeNames, because we don't know
+        // surrounding context - the Foo.Bar.Baz type can be referred to as `Baz` inside Foo.Bar
+        return identifierType.name.text == typeName
+      } else if let memberType = currType.as(MemberTypeSyntax.self) {
+        if memberType.name.text != typeName {
+          return false
+        }
+        currType = memberType.baseType
+      } else {
+        return false
+      }
+    }
+
+    return false
+  }
+}
diff --git a/Tests/SwiftSyntaxTest/UtilsTests.swift b/Tests/SwiftSyntaxTest/UtilsTests.swift
new file mode 100644
index 00000000000..c90fc41bc08
--- /dev/null
+++ b/Tests/SwiftSyntaxTest/UtilsTests.swift
@@ -0,0 +1,76 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2024 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+import SwiftSyntax
+import XCTest
+
+class UtilsTests: XCTestCase {
+
+  public func testIsVoid() {
+    XCTAssertTrue(TypeSyntax("Void").isVoid)
+    XCTAssertTrue(TypeSyntax("Swift.Void").isVoid)
+    XCTAssertTrue(TypeSyntax("()").isVoid)
+
+    XCTAssertFalse(TypeSyntax("(Int, Int)").isVoid)
+    XCTAssertFalse(TypeSyntax("Swift").isVoid)
+    XCTAssertFalse(TypeSyntax("Swift.()").isVoid)
+    XCTAssertFalse(TypeSyntax("Int").isVoid)
+    XCTAssertFalse(TypeSyntax("(())").isVoid)
+    XCTAssertFalse(TypeSyntax("(Void)").isVoid)
+  }
+
+  public func testIsInt() {
+    XCTAssertTrue(TypeSyntax("Int").canRepresentBasicType(type: Int.self))
+    XCTAssertTrue(TypeSyntax("Swift.Int").canRepresentBasicType(type: Int.self))
+    XCTAssertTrue(TypeSyntax("Int").canRepresentBasicType(type: Swift.Int.self))
+    XCTAssertTrue(TypeSyntax("Swift.Int").canRepresentBasicType(type: Swift.Int.self))
+
+    // Only the canonical type syntax matches
+    XCTAssertFalse(TypeSyntax("CInt").canRepresentBasicType(type: Int.self))
+    XCTAssertFalse(TypeSyntax("Swift.CInt").canRepresentBasicType(type: Int.self))
+    XCTAssertFalse(TypeSyntax("CInt").canRepresentBasicType(type: Swift.Int.self))
+    XCTAssertFalse(TypeSyntax("Swift.CInt").canRepresentBasicType(type: Swift.Int.self))
+  }
+
+  public func testIsCInt() {
+    // Match against the canonical type (platform dependent)
+    XCTAssertEqual(TypeSyntax("Swift.Int").canRepresentBasicType(type: Swift.CInt.self), CInt.self == Int.self)
+    XCTAssertEqual(TypeSyntax("Int").canRepresentBasicType(type: Swift.CInt.self), CInt.self == Int.self)
+    XCTAssertEqual(TypeSyntax("Int").canRepresentBasicType(type: CInt.self), CInt.self == Int.self)
+    XCTAssertEqual(TypeSyntax("Swift.Int").canRepresentBasicType(type: CInt.self), CInt.self == Int.self)
+
+    XCTAssertFalse(TypeSyntax("Swift.CInt").canRepresentBasicType(type: Swift.CInt.self))
+    XCTAssertFalse(TypeSyntax("CInt").canRepresentBasicType(type: Swift.CInt.self))
+    XCTAssertFalse(TypeSyntax("CInt").canRepresentBasicType(type: CInt.self))
+    XCTAssertFalse(TypeSyntax("Swift.CInt").canRepresentBasicType(type: CInt.self))
+  }
+
+  public func testIsArrayType() {
+    // Only plain name types are supported
+    XCTAssertFalse(TypeSyntax("[Int]").canRepresentBasicType(type: [Int].self))
+    XCTAssertFalse(TypeSyntax("Int").canRepresentBasicType(type: [Int].self))
+  }
+
+  public func testIsOptionalType() {
+    // Only plain name types are supported
+    XCTAssertFalse(TypeSyntax("Int?").canRepresentBasicType(type: Int?.self))
+    XCTAssertFalse(TypeSyntax("Optional<Int>").canRepresentBasicType(type: Int?.self))
+    XCTAssertFalse(TypeSyntax("Int").canRepresentBasicType(type: [Int].self))
+  }
+
+  public func testIsTupleTypes() {
+    // Only plain name types are supported
+    XCTAssertFalse(TypeSyntax("()").canRepresentBasicType(type: Void.self))
+    XCTAssertFalse(TypeSyntax("Void").canRepresentBasicType(type: Void.self))
+    XCTAssertFalse(TypeSyntax("(Int, Int)").canRepresentBasicType(type: (Int, Int).self))
+  }
+}
\ No newline at end of file