Class: Dependabot::Swift::FileParser::PbxprojParser

Inherits:
Object
  • Object
show all
Extended by:
T::Sig
Defined in:
lib/dependabot/swift/file_parser/pbxproj_parser.rb

Overview

Parses XCRemoteSwiftPackageReference entries from a project.pbxproj file to extract dependency requirement constraints declared in Xcode.

Returns a hash keyed by normalized dependency name (e.g. “github.com/owner/repo”) mapping to requirement metadata, so the main parser can enrich Package.resolved dependencies with requirement info from the Xcode project.

Constant Summary collapse

PACKAGE_REF_BLOCK =

Regex to extract XCRemoteSwiftPackageReference blocks from pbxproj. Uses [^}]* to match the requirement block content — this is safe because Xcode requirement blocks are always flat dictionaries with no nested braces.

T.let(
  /
    isa\s*=\s*XCRemoteSwiftPackageReference;\s*
    repositoryURL\s*=\s*"(?<url>[^"]+)";\s*
    requirement\s*=\s*\{(?<requirement>[^}]*)\};
  /mx,
  Regexp
)
KIND_PATTERN =

Patterns for extracting requirement fields

T.let(/kind\s*=\s*(\w+);/, Regexp)
VERSION_NUMBER_PATTERN =
T.let(/[0-9A-Za-z.+-]+/, Regexp)
MIN_VERSION_PATTERN =
T.let(/minimumVersion\s*=\s*(#{VERSION_NUMBER_PATTERN});/, Regexp)
MAX_VERSION_PATTERN =
T.let(/maximumVersion\s*=\s*(#{VERSION_NUMBER_PATTERN});/, Regexp)
VERSION_PATTERN =
T.let(/version\s*=\s*(#{VERSION_NUMBER_PATTERN});/, Regexp)
BRANCH_PATTERN =
T.let(/branch\s*=\s*"?([^";]+)"?;/, Regexp)
REVISION_PATTERN =
T.let(/revision\s*=\s*"?([^";]+)"?;/, Regexp)

Instance Method Summary collapse

Constructor Details

#initialize(pbxproj_file) ⇒ PbxprojParser

Returns a new instance of PbxprojParser.



45
46
47
# File 'lib/dependabot/swift/file_parser/pbxproj_parser.rb', line 45

def initialize(pbxproj_file)
  @pbxproj_file = pbxproj_file
end

Instance Method Details

#parseObject



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/dependabot/swift/file_parser/pbxproj_parser.rb', line 53

def parse
  content = pbxproj_file.content
  return {} unless content

  requirements = T.let({}, T::Hash[String, T::Hash[Symbol, T.untyped]])

  content.scan(PACKAGE_REF_BLOCK).each do |url, requirement_block|
    url = T.cast(url, String)
    requirement_block = T.cast(requirement_block, String)
    normalized_url = SharedHelpers.scp_to_standard(url)
    name = UrlHelpers.normalize_name(normalized_url)

    req_info = parse_requirement_block(requirement_block)
    next unless req_info

    requirements[name] = req_info.merge(
      url: normalized_url,
      file: pbxproj_file.name
    )
  end

  requirements
end