├── ChatGPT
├── Assets.xcassets
│ ├── Contents.json
│ ├── AccentColor.colorset
│ │ └── Contents.json
│ └── AppIcon.appiconset
│ │ └── Contents.json
├── Preview Content
│ └── Preview Assets.xcassets
│ │ └── Contents.json
├── ChatGPTApp.swift
├── ChatGPT.entitlements
└── ContentView.swift
├── ChatGPT.xcodeproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
├── xcuserdata
│ └── adolfo.xcuserdatad
│ │ ├── xcdebugger
│ │ └── Breakpoints_v2.xcbkptlist
│ │ └── xcschemes
│ │ └── xcschememanagement.plist
├── xcshareddata
│ └── xcschemes
│ │ ├── ChatGPT.xcscheme
│ │ └── ChatGPTExtension.xcscheme
└── project.pbxproj
├── ChatGPTExtension
├── Domain
│ ├── Model
│ │ ├── Suggestion.swift
│ │ └── ConverterError.swift
│ ├── UseCase
│ │ ├── AnalyzeUseCase.swift
│ │ ├── Regex
│ │ │ ├── RegexUseCase.swift
│ │ │ └── DefaultRegexUseCase.swift
│ │ ├── Comments
│ │ │ ├── CommentUseCase.swift
│ │ │ └── DefaultCommentUseCase.swift
│ │ ├── ExplainCode
│ │ │ ├── ExplainCodeUseCase.swift
│ │ │ └── DefaultExplainCodeUseCase.swift
│ │ ├── JSON2Swift
│ │ │ ├── JSONConverterUseCase.swift
│ │ │ └── DefaultJSONConverterUseCase.swift
│ │ ├── UnitTest
│ │ │ ├── UnitTestUseCase.swift
│ │ │ └── DefaultUnitTestUseCase.swift
│ │ └── CodeSmells
│ │ │ ├── CodeSmellsUseCase.swift
│ │ │ └── DefaultCodeSmellsUseCase.swift
│ └── Repositories
│ │ ├── CommentRepository.swift
│ │ ├── JSONConverterRepository.swift
│ │ ├── RegexRepository.swift
│ │ ├── ExplainCodeRepository.swift
│ │ ├── UnitTestRepository.swift
│ │ └── CodeSmellsRepository.swift
├── ChatGPTExtension.entitlements
├── Data
│ ├── Network
│ │ └── OpenAI
│ │ │ ├── Model
│ │ │ ├── ChatGPTError.swift
│ │ │ ├── Constants.swift
│ │ │ ├── ChatGPTRequest.swift
│ │ │ ├── ChatGPTResponse.swift
│ │ │ └── NetworkRequest.swift
│ │ │ ├── Extensions
│ │ │ └── OpenAI+Localizable.swift
│ │ │ ├── Resources
│ │ │ ├── es.lproj
│ │ │ │ └── Localizable.strings
│ │ │ └── en.lproj
│ │ │ │ └── Localizable.strings
│ │ │ ├── OpenAI+Operations.swift
│ │ │ └── OpenAI.swift
│ └── Repositories
│ │ ├── BaseChatGPTRepository.swift
│ │ ├── ChatGPTCommentRepository.swift
│ │ ├── ChatGPTExplainCodeRepository.swift
│ │ ├── ChatGPTJSONConverterRepository.swift
│ │ ├── ChatGPTRegexRepository.swift
│ │ ├── ChatGPTCodeSmellsRepository.swift
│ │ └── ChatGPTUnitTestRepository.swift
├── Commands
│ ├── SourceEditorExtension.swift
│ ├── ExplainCode
│ │ └── ExplainCodeCommand.swift
│ ├── JSON2Swift
│ │ └── JSON2SwiftEditorCommand.swift
│ ├── UnitTest
│ │ └── UnitTestEditorCommand.swift
│ ├── CodeSmells
│ │ └── CodeSmellsEditorCommand.swift
│ ├── Comment
│ │ └── CommentCommand.swift
│ └── Regex
│ │ └── RegexCommand.swift
├── Infrastructure
│ └── Dependencies
│ │ └── DependencyManager.swift
└── Info.plist
├── .github
└── workflows
│ └── code-review.yml
├── README.md
└── .gitignore
/ChatGPT/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/ChatGPT/Preview Content/Preview Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/ChatGPT.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ChatGPT/Assets.xcassets/AccentColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "idiom" : "universal"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/ChatGPT.xcodeproj/xcuserdata/adolfo.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Domain/Model/Suggestion.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Suggestion.swift
3 | // ChatGPTExtension
4 | //
5 | // Created by Adolfo Vera Blasco on 4/3/23.
6 | //
7 |
8 | import Foundation
9 |
10 | struct Suggestion {
11 | let result: String
12 | }
13 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Domain/UseCase/AnalyzeUseCase.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AnalyzeUseCase.swift
3 | // ChatGPTExtension
4 | //
5 | // Created by Adolfo Vera Blasco on 4/3/23.
6 | //
7 |
8 | import Foundation
9 |
10 | protocol JSONConverterUseCase {
11 | func analyze(source code: [String]) async -> Suggestion
12 | }
13 |
--------------------------------------------------------------------------------
/ChatGPT/ChatGPTApp.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ChatGPTApp.swift
3 | // ChatGPT
4 | //
5 | // Created by Adolfo Vera Blasco on 3/3/23.
6 | //
7 |
8 | import SwiftUI
9 |
10 | @main
11 | struct ChatGPTApp: App {
12 | var body: some Scene {
13 | WindowGroup {
14 | ContentView()
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Domain/UseCase/Regex/RegexUseCase.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RegexUseCase.swift
3 | // ChatGPTExtension
4 | //
5 | // Created by Adolfo Vera Blasco on 20/3/23.
6 | //
7 |
8 | import Foundation
9 |
10 | protocol RegexUseCase {
11 | func generateRegexFor(string value: String) async throws -> Suggestion
12 | }
13 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Domain/UseCase/Comments/CommentUseCase.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CommentUseCase.swift
3 | // ChatGPTExtension
4 | //
5 | // Created by Adolfo Vera Blasco on 22/3/23.
6 | //
7 |
8 | import Foundation
9 |
10 | protocol CommentUseCase {
11 | func comment(function code: [String]) async throws -> Suggestion
12 | }
13 |
--------------------------------------------------------------------------------
/ChatGPT.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Domain/Repositories/CommentRepository.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CommentRepository.swift
3 | // ChatGPTExtension
4 | //
5 | // Created by Adolfo Vera Blasco on 22/3/23.
6 | //
7 |
8 | import Foundation
9 |
10 | protocol CommentRepository {
11 | func comment(function code: String) async throws -> [Suggestion]
12 | }
13 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Domain/Repositories/JSONConverterRepository.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AnalyzeRepository.swift
3 | // ChatGPTExtension
4 | //
5 | // Created by Adolfo Vera Blasco on 4/3/23.
6 | //
7 |
8 | import Foundation
9 |
10 | protocol JSONConverterRepository {
11 | func analyze(code: String) async throws -> [Suggestion]
12 | }
13 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Domain/Repositories/RegexRepository.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RegexRepository.swift
3 | // ChatGPTExtension
4 | //
5 | // Created by Adolfo Vera Blasco on 20/3/23.
6 | //
7 |
8 | import Foundation
9 |
10 | protocol RegexRepository {
11 | func generateRegexFor(string value: String) async throws -> [Suggestion]
12 | }
13 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Domain/Repositories/ExplainCodeRepository.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ExplainCodeRepository.swift
3 | // ChatGPTExtension
4 | //
5 | // Created by Adolfo Vera Blasco on 5/3/23.
6 | //
7 |
8 | import Foundation
9 |
10 | protocol ExplainCodeRepository {
11 | func explainMeThis(code: String) async throws -> [Suggestion]
12 | }
13 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Domain/UseCase/ExplainCode/ExplainCodeUseCase.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ExplainCodeUseCase.swift
3 | // ChatGPTExtension
4 | //
5 | // Created by Adolfo Vera Blasco on 5/3/23.
6 | //
7 |
8 | import Foundation
9 |
10 | protocol ExplainCodeUseCase {
11 | func explainMeThis(code: String) async throws -> Suggestion
12 | }
13 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Domain/UseCase/JSON2Swift/JSONConverterUseCase.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AnalyzeUseCase.swift
3 | // ChatGPTExtension
4 | //
5 | // Created by Adolfo Vera Blasco on 4/3/23.
6 | //
7 |
8 | import Foundation
9 |
10 | protocol JSONConverterUseCase {
11 | func analyze(source code: [String]) async throws -> Suggestion
12 | }
13 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Domain/UseCase/UnitTest/UnitTestUseCase.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UnitTestUseCase.swift
3 | // ChatGPTExtension
4 | //
5 | // Created by Adolfo Vera Blasco on 19/3/23.
6 | //
7 |
8 | import Foundation
9 |
10 | protocol UnitTestUseCase {
11 | func generateTestsFor(source code: [String]) async throws -> Suggestion
12 | }
13 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Domain/Repositories/UnitTestRepository.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UnitTestRepository.swift
3 | // ChatGPTExtension
4 | //
5 | // Created by Adolfo Vera Blasco on 19/3/23.
6 | //
7 |
8 | import Foundation
9 |
10 | protocol UnitTestRepository {
11 | func generateTestsFor(source code: String) async throws -> [Suggestion]
12 | }
13 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Domain/UseCase/CodeSmells/CodeSmellsUseCase.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CodeSmellsUseCase.swift
3 | // ChatGPTExtension
4 | //
5 | // Created by Adolfo Vera Blasco on 4/3/23.
6 | //
7 |
8 | import Foundation
9 |
10 | protocol CodeSmellsUseCase {
11 | func searchForCodeSmells(in code: [String]) async throws -> Suggestion
12 | }
13 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Domain/Repositories/CodeSmellsRepository.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CodeSmellsRepository.swift
3 | // ChatGPTExtension
4 | //
5 | // Created by Adolfo Vera Blasco on 4/3/23.
6 | //
7 |
8 | import Foundation
9 |
10 | protocol CodeSmellsRepository {
11 | func searchForCodeSmells(in code: String) async throws -> [Suggestion]
12 | }
13 |
--------------------------------------------------------------------------------
/ChatGPTExtension/ChatGPTExtension.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 | com.apple.security.network.client
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Domain/Model/ConverterError.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ConverterError.swift
3 | // ChatGPTExtension
4 | //
5 | // Created by Adolfo Vera Blasco on 4/3/23.
6 | //
7 |
8 | import Foundation
9 |
10 | enum ConverterError: Error {
11 | case emptyResults
12 | case authorization
13 | case rateLimit
14 | case serverStatus
15 | case unknownResponse
16 | }
17 |
--------------------------------------------------------------------------------
/ChatGPT/ChatGPT.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 | com.apple.security.files.user-selected.read-only
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Data/Network/OpenAI/Model/ChatGPTError.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ChatGPTError.swift
3 | // ChatGPTExtension
4 | //
5 | // Created by Adolfo Vera Blasco on 4/3/23.
6 | //
7 |
8 | import Foundation
9 |
10 | enum ChatGPTError: Error {
11 | case malformedURL(value: String)
12 | case authentication
13 | case rateLimitReached
14 | case serverError
15 | case unknownServerResponse
16 | case malformedResponse
17 | }
18 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Data/Network/OpenAI/Extensions/OpenAI+Localizable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OpenAI+Localizable.swift
3 | // ChatGPTExtension
4 | //
5 | // Created by Adolfo Vera Blasco on 4/3/23.
6 | //
7 |
8 | import Foundation
9 |
10 | extension OpenAI {
11 | func localizedPrompt(_ key: String) -> String {
12 | let openAIBundle = Bundle(for: Self.self)
13 |
14 | return NSLocalizedString(key, bundle: openAIBundle, comment: "")
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/ChatGPT/ContentView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ContentView.swift
3 | // ChatGPT
4 | //
5 | // Created by Adolfo Vera Blasco on 3/3/23.
6 | //
7 |
8 | import SwiftUI
9 |
10 | struct ContentView: View {
11 | var body: some View {
12 | Text("ChatGPT & Xcode")
13 | .font(.largeTitle)
14 | .fontWidth(.condensed)
15 | .frame(maxWidth: .infinity, alignment: .center)
16 | .padding()
17 | }
18 | }
19 |
20 | struct ContentView_Previews: PreviewProvider {
21 | static var previews: some View {
22 | ContentView()
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/.github/workflows/code-review.yml:
--------------------------------------------------------------------------------
1 | name: GlobantBot Code Review
2 |
3 | permissions:
4 | contents: read
5 | pull-requests: write
6 |
7 | on:
8 | pull_request:
9 | types: [opened, reopened]
10 |
11 | jobs:
12 | code-review:
13 | runs-on: ubuntu-latest
14 | steps:
15 | - uses: fitomad/github-chatgpt-integration@main
16 | with:
17 | openai-api-key: ${{ secrets.OPENAI_API_KEY }}
18 | github-token: ${{ secrets.GH_TOKEN }}
19 | github-pr-id: ${{ github.event.number }}
20 | dev-lang: Swift
21 | openai-max-tokens: 4096
22 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Data/Network/OpenAI/Resources/es.lproj/Localizable.strings:
--------------------------------------------------------------------------------
1 | /*
2 | Localizable.strings
3 | ChatGPT
4 |
5 | Created by Adolfo Vera Blasco on 4/3/23.
6 |
7 | */
8 |
9 | "PROMPT_JSON" = "Convierte este JSON a una estructura Swift Codable pero sin la implementación";
10 | "PROMPT_CODE_SMELLS" = "Busca posibles Code Smells en este código escrito en Swift";
11 | "PROMPT_EXPLAIN_CODE" = "¿Qué hace este código escrito en Swift?";
12 | "PROMPT_GENERATE_UNIT_TEST" = "Genera las pruebas para este código usando el framework XCTest";
13 | "PROMPT_REGEX" = "Genera una expresión regular en Swift que represente esta cadena de texto";
14 |
15 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Data/Network/OpenAI/Model/Constants.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Constants.swift
3 | // ChatGPTExtension
4 | //
5 | // Created by Adolfo Vera Blasco on 3/3/23.
6 | //
7 |
8 | import Foundation
9 |
10 | enum Constants {
11 | static let baseURL = "https://api.openai.com/v1/chat/completions"
12 |
13 | static let contentTypeHeaderKey = "Content-Type"
14 | static let contentTypeHeaderValue = "application/json"
15 |
16 | static let authorizationHeaderKey = "Authorization"
17 | static let authorizationHeaderValue = "Bearer"
18 |
19 | static let modelChatpGPT = "gpt-3.5-turbo"
20 | static let modelChatGPTUser = "user"
21 | }
22 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Data/Network/OpenAI/Model/ChatGPTRequest.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ChatGPTRequest.swift
3 | // ChatGPTExtension
4 | //
5 | // Created by Adolfo Vera Blasco on 4/3/23.
6 | //
7 |
8 | import Foundation
9 |
10 | struct ChatGPTRequest: Encodable {
11 | let model = Constants.modelChatpGPT
12 | let messages: [ChatGPTRequest.Message]
13 |
14 | init(prompt: String) {
15 | let message = ChatGPTRequest.Message(content: prompt)
16 |
17 | self.messages = [
18 | message
19 | ]
20 | }
21 | }
22 |
23 | extension ChatGPTRequest {
24 | struct Message: Encodable {
25 | let role = Constants.modelChatGPTUser
26 | let content: String
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Data/Network/OpenAI/Resources/en.lproj/Localizable.strings:
--------------------------------------------------------------------------------
1 | /*
2 | Localizable.strings
3 | ChatGPT
4 |
5 | Created by Adolfo Vera Blasco on 4/3/23.
6 |
7 | */
8 |
9 | "PROMPT_JSON" = "Convert this JSON to a Swift Codable data structure only struct declaration";
10 | "PROMPT_CODE_SMELLS" = "Check for Code Smells in this Swift code";
11 | "PROMPT_EXPLAIN_CODE" = "What this Swift code does?";
12 | "PROMPT_GENERATE_UNIT_TEST" = "Write the test cases in Swift for this code using the XCTest framework.";
13 | "PROMPT_REGEX" = "Generate a regular expression using Regex to match";
14 | "PROMPT_COMMENT" = "Generate comments in Swift format for this function, indicating the parameters and return type, with a max line lenght of 80 characters";
15 |
16 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Data/Repositories/BaseChatGPTRepository.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BaseChatGPTRepository.swift
3 | // ChatGPTExtension
4 | //
5 | // Created by Adolfo Vera Blasco on 4/3/23.
6 | //
7 |
8 | import Foundation
9 |
10 | class BaseChatGPTRepository {
11 | func fetchApiKey() -> String? {
12 | let currentBundle = Bundle(for: Self.self)
13 |
14 | guard let apiKeyURL = currentBundle.url(forResource: "openai", withExtension: "environment"),
15 | var apiKey = try? String(contentsOf: apiKeyURL, encoding: .utf8)
16 | else
17 | {
18 | return nil
19 | }
20 |
21 | apiKey = apiKey.trimmingCharacters(in: .whitespacesAndNewlines)
22 |
23 | return apiKey
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Domain/UseCase/Regex/DefaultRegexUseCase.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DefaultRegexUseCase.swift
3 | // ChatGPTExtension
4 | //
5 | // Created by Adolfo Vera Blasco on 20/3/23.
6 | //
7 |
8 | import Foundation
9 |
10 | final class DefaultRegexUseCase: RegexUseCase {
11 | private let repository: RegexRepository
12 |
13 | init(repository: RegexRepository) {
14 | self.repository = repository
15 | }
16 |
17 | func generateRegexFor(string value: String) async throws -> Suggestion {
18 | let suggestions = try await self.repository.generateRegexFor(string: value)
19 |
20 | guard let suggestion = suggestions.first else {
21 | throw ConverterError.emptyResults
22 | }
23 |
24 | return suggestion
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Domain/UseCase/ExplainCode/DefaultExplainCodeUseCase.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DefaultExplainCodeUseCase.swift
3 | // ChatGPTExtension
4 | //
5 | // Created by Adolfo Vera Blasco on 5/3/23.
6 | //
7 |
8 | import Foundation
9 |
10 | final class DefaultExplainCodeUseCase: ExplainCodeUseCase {
11 | private let repository: ExplainCodeRepository
12 |
13 | init(repository: ExplainCodeRepository) {
14 | self.repository = repository
15 | }
16 |
17 | func explainMeThis(code: String) async throws -> Suggestion {
18 | let suggestions = try await self.repository.explainMeThis(code: code)
19 |
20 | guard let suggestion = suggestions.first else {
21 | throw ConverterError.emptyResults
22 | }
23 |
24 | return suggestion
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Domain/UseCase/Comments/DefaultCommentUseCase.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DefaultCommentUseCase.swift
3 | // ChatGPTExtension
4 | //
5 | // Created by Adolfo Vera Blasco on 22/3/23.
6 | //
7 |
8 | import Foundation
9 |
10 | final class DefaultCommentUseCase: CommentUseCase {
11 | private let repository: CommentRepository
12 |
13 | init(repository: CommentRepository) {
14 | self.repository = repository
15 | }
16 |
17 | func comment(function code: [String]) async throws -> Suggestion {
18 | let preparedCode = code.reduce("") { $0 + $1 }
19 |
20 | let suggestions = try await self.repository.comment(function: preparedCode)
21 |
22 | guard let suggestion = suggestions.first else {
23 | throw ConverterError.emptyResults
24 | }
25 |
26 | return suggestion
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Domain/UseCase/UnitTest/DefaultUnitTestUseCase.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DefaultUnitTestUseCase.swift
3 | // ChatGPTExtension
4 | //
5 | // Created by Adolfo Vera Blasco on 19/3/23.
6 | //
7 |
8 | import Foundation
9 |
10 | final class DefaultUnitTestUseCase: UnitTestUseCase {
11 | private let repository: UnitTestRepository
12 |
13 | init(repository: UnitTestRepository) {
14 | self.repository = repository
15 | }
16 |
17 | func generateTestsFor(source code: [String]) async throws -> Suggestion {
18 | let lines = code.reduce("") { $0 + $1 }
19 |
20 | let suggestions = try await self.repository.generateTestsFor(source: lines)
21 |
22 | guard let suggestion = suggestions.first else {
23 | throw ConverterError.emptyResults
24 | }
25 |
26 | return suggestion
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Domain/UseCase/JSON2Swift/DefaultJSONConverterUseCase.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DefaultAnalyzeUseCase.swift
3 | // ChatGPTExtension
4 | //
5 | // Created by Adolfo Vera Blasco on 4/3/23.
6 | //
7 |
8 | import Foundation
9 |
10 | final class DefaultJSONConverterUseCase: JSONConverterUseCase {
11 | let repository: JSONConverterRepository
12 |
13 | init(repository: JSONConverterRepository) {
14 | self.repository = repository
15 | }
16 |
17 | func analyze(source code: [String]) async throws -> Suggestion {
18 | let preparedCode = code.reduce("") { $0 + $1 }
19 |
20 | let suggestions = try await self.repository.analyze(code: preparedCode)
21 |
22 | guard let suggestion = suggestions.first else {
23 | throw ConverterError.emptyResults
24 | }
25 |
26 | return suggestion
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Domain/UseCase/CodeSmells/DefaultCodeSmellsUseCase.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DefaultCodeSmellsUseCase.swift
3 | // ChatGPTExtension
4 | //
5 | // Created by Adolfo Vera Blasco on 4/3/23.
6 | //
7 |
8 | import Foundation
9 |
10 | final class DefaultCodeSmellsUseCase: CodeSmellsUseCase {
11 | let repository: CodeSmellsRepository
12 |
13 | init(repository: CodeSmellsRepository) {
14 | self.repository = repository
15 | }
16 |
17 | func searchForCodeSmells(in code: [String]) async throws -> Suggestion {
18 | let preparedCode = code.reduce("") { $0 + $1 }
19 |
20 | let suggestions = try await self.repository.searchForCodeSmells(in: preparedCode)
21 |
22 | guard let suggestion = suggestions.first else {
23 | throw ConverterError.emptyResults
24 | }
25 |
26 | return suggestion
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/ChatGPT.xcodeproj/xcuserdata/adolfo.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | ChatGPT.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 0
11 |
12 | ChatGPTExtension.xcscheme_^#shared#^_
13 |
14 | orderHint
15 | 1
16 |
17 |
18 | SuppressBuildableAutocreation
19 |
20 | 91FFEE4C29B2822000B4DE2A
21 |
22 | primary
23 |
24 |
25 | 91FFEE6229B2824B00B4DE2A
26 |
27 | primary
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Commands/SourceEditorExtension.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SourceEditorExtension.swift
3 | // ChatGPTExtension
4 | //
5 | // Created by Adolfo Vera Blasco on 3/3/23.
6 | //
7 |
8 | import Foundation
9 | import XcodeKit
10 |
11 | class SourceEditorExtension: NSObject, XCSourceEditorExtension {
12 |
13 | /*
14 | func extensionDidFinishLaunching() {
15 | // If your extension needs to do any work at launch, implement this optional method.
16 | }
17 | */
18 |
19 | /*
20 | var commandDefinitions: [[XCSourceEditorCommandDefinitionKey: Any]] {
21 | // If your extension needs to return a collection of command definitions that differs from those in its Info.plist, implement this optional property getter.
22 | return [
23 | [
24 | .classNameKey : "SourceEditorCommand",
25 | .identifierKey : "SourceEditorCommand",
26 | .nameKey : "ChatGPT"
27 | ]
28 | ]
29 | }
30 | */
31 | }
32 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Commands/ExplainCode/ExplainCodeCommand.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ExplainCodeCommand.swift
3 | // ChatGPTExtension
4 | //
5 | // Created by Adolfo Vera Blasco on 5/3/23.
6 | //
7 |
8 | import Foundation
9 | import XcodeKit
10 |
11 | final class ExplainCodeCommand: NSObject, XCSourceEditorCommand {
12 | let useCase: ExplainCodeUseCase = DependencyManager.makeExplainCodeDependencies()
13 |
14 | func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: @escaping (Error?) -> Void) {
15 | Task {
16 | let fileSourceCode = invocation.buffer.completeBuffer
17 |
18 | do {
19 | let suggestion = try await self.useCase.explainMeThis(code: fileSourceCode)
20 |
21 | let insertedExplanation = "/**\n\(suggestion.result)\n*/"
22 |
23 | invocation.buffer.lines.add(insertedExplanation)
24 | } catch let error {
25 | print("🚨 Something goes wrong... \(error)")
26 | }
27 |
28 | completionHandler(nil)
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Commands/JSON2Swift/JSON2SwiftEditorCommand.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SourceEditorCommand.swift
3 | // ChatGPTExtension
4 | //
5 | // Created by Adolfo Vera Blasco on 3/3/23.
6 | //
7 |
8 | import Foundation
9 | import XcodeKit
10 |
11 | class JSON2SwiftEditorCommand: NSObject, XCSourceEditorCommand {
12 | let useCase: JSONConverterUseCase = DependencyManager.makeAnalyzeDependencies()
13 |
14 | func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: @escaping (Error?) -> Void ) -> Void {
15 | guard let codeLines = invocation.buffer.lines as? [String] else {
16 | completionHandler(nil)
17 | return
18 | }
19 |
20 | Task {
21 | do {
22 | let suggestion = try await self.useCase.analyze(source: codeLines)
23 |
24 | invocation.buffer.selections.removeAllObjects()
25 | invocation.buffer.selections.add(suggestion.result)
26 | } catch let error {
27 | print("🚨 Something goes wrong... \(error)")
28 | }
29 |
30 | completionHandler(nil)
31 | }
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/ChatGPT/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "scale" : "1x",
6 | "size" : "16x16"
7 | },
8 | {
9 | "idiom" : "mac",
10 | "scale" : "2x",
11 | "size" : "16x16"
12 | },
13 | {
14 | "idiom" : "mac",
15 | "scale" : "1x",
16 | "size" : "32x32"
17 | },
18 | {
19 | "idiom" : "mac",
20 | "scale" : "2x",
21 | "size" : "32x32"
22 | },
23 | {
24 | "idiom" : "mac",
25 | "scale" : "1x",
26 | "size" : "128x128"
27 | },
28 | {
29 | "idiom" : "mac",
30 | "scale" : "2x",
31 | "size" : "128x128"
32 | },
33 | {
34 | "idiom" : "mac",
35 | "scale" : "1x",
36 | "size" : "256x256"
37 | },
38 | {
39 | "idiom" : "mac",
40 | "scale" : "2x",
41 | "size" : "256x256"
42 | },
43 | {
44 | "idiom" : "mac",
45 | "scale" : "1x",
46 | "size" : "512x512"
47 | },
48 | {
49 | "idiom" : "mac",
50 | "scale" : "2x",
51 | "size" : "512x512"
52 | }
53 | ],
54 | "info" : {
55 | "author" : "xcode",
56 | "version" : 1
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Commands/UnitTest/UnitTestEditorCommand.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UnitTestEditorCommand.swift
3 | // ChatGPTExtension
4 | //
5 | // Created by Adolfo Vera Blasco on 19/3/23.
6 | //
7 |
8 | import Foundation
9 | import XcodeKit
10 |
11 | final class UnitTestEditorCommand: NSObject, XCSourceEditorCommand {
12 | let useCase: UnitTestUseCase = DependencyManager.makeUnitTestsDependencies()
13 |
14 | func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: @escaping (Error?) -> Void) {
15 | guard let codeLines = invocation.buffer.lines as? [String] else {
16 | completionHandler(nil)
17 | return
18 | }
19 |
20 | Task {
21 | do {
22 | let suggestion = try await self.useCase.generateTestsFor(source: codeLines)
23 |
24 | let insertedExplanation = "/**\n\(suggestion.result)\n*/"
25 |
26 | invocation.buffer.lines.add(insertedExplanation)
27 | } catch let error {
28 | print("🚨 Something goes wrong... \(error)")
29 | }
30 |
31 | completionHandler(nil)
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Commands/CodeSmells/CodeSmellsEditorCommand.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CodeSmellsEditorCommand.swift
3 | // ChatGPTExtension
4 | //
5 | // Created by Adolfo Vera Blasco on 4/3/23.
6 | //
7 |
8 | import Foundation
9 | import XcodeKit
10 |
11 | final class CodeSmellsEditorCommand: NSObject, XCSourceEditorCommand {
12 | let useCase: CodeSmellsUseCase = DependencyManager.makeCodeSmellsDependencies()
13 |
14 | func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: @escaping (Error?) -> Void ) -> Void {
15 | guard let codeLines = invocation.buffer.lines as? [String] else {
16 | completionHandler(nil)
17 | return
18 | }
19 |
20 | Task {
21 | do {
22 | let suggestion = try await self.useCase.searchForCodeSmells(in: codeLines)
23 |
24 | let insertedSuggestion = "/**\(suggestion.result)\n*/"
25 |
26 | invocation.buffer.lines.add(insertedSuggestion)
27 | } catch let error {
28 | print("🚨 Something goes wrong... \(error)")
29 | }
30 |
31 | completionHandler(nil)
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Data/Network/OpenAI/Model/ChatGPTResponse.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ChatGPTResponse.swift
3 | // ChatGPTExtension
4 | //
5 | // Created by Adolfo Vera Blasco on 4/3/23.
6 | //
7 |
8 | import Foundation
9 |
10 | struct ChatGPTResponse: Decodable, Identifiable {
11 | let id: String
12 | let object: String
13 | let model: String
14 | let usage: ChatGPTResponse.Usage
15 | let choices: [ChatGPTResponse.Choice]
16 | }
17 |
18 | extension ChatGPTResponse {
19 | struct Usage: Decodable {
20 | let promptTokenCount: Int
21 | let completionTokenCount: Int
22 | let totalTokens: Int
23 |
24 | private enum CodingKeys: String, CodingKey {
25 | case promptTokenCount = "prompt_tokens"
26 | case completionTokenCount = "completion_tokens"
27 | case totalTokens = "total_tokens"
28 | }
29 | }
30 |
31 | struct Message: Decodable {
32 | let role: String
33 | let content: String
34 | }
35 |
36 | struct Choice: Decodable {
37 | let message: ChatGPTResponse.Message
38 | let finishReason: String
39 | let index: Int
40 |
41 | private enum CodingKeys: String, CodingKey {
42 | case message
43 | case finishReason = "finish_reason"
44 | case index
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ChatGPT-Xcode
2 |
3 | This repository serves as the basis for the Medium article titled ["Integrating ChatGPT into Xcode: How to Improve Your Apps with AI."](https://medium.com/globant/chatgpt-integration-in-xcode-how-to-improve-your-apps-with-ai-3bdbc34bea48)
4 |
5 | Integrating ChatGPT into Xcode using an Xcode Source Editor Extension that solves three specific problems:
6 |
7 | * **Code conversion**. A command that converts a JSON document to a Swift struct.
8 | * **Code smells**. We ask ChatGPT to try to identify things that can be improved in our source code.
9 | * **Code explanation**. In this last case, we are interested in knowing what a particular code does.
10 | * **Unit testing**. Generate XCTest code for the current file.
11 | * **Regex**. Creates a regular expression based on the selected text string.
12 |
13 | ## OpenAI API Key
14 |
15 | To execute the extension commands, an OpenAI API key is required, which must be saved in a file called `openai.environment` and will only contain the key.
16 |
17 | This file must be included in the Xcode extension target.
18 |
19 | ## Disclaimer. Read carefully
20 |
21 | Usage of this Source Code Extension will **send your source code to ChatGPT**, please note that due to the nature of the internet, It does not guarantee the security of any information transmitted to OpenAI, including source code.
22 |
23 | Before using code that you don't own with this Source Code Extension, contact its owner to obtain the necessary permission.
24 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Data/Repositories/ChatGPTCommentRepository.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ChatGPTCommentRepository.swift
3 | // ChatGPTExtension
4 | //
5 | // Created by Adolfo Vera Blasco on 22/3/23.
6 | //
7 |
8 | import Foundation
9 |
10 | final class ChatGPTCommentRepository: BaseChatGPTRepository, CommentRepository {
11 | func comment(function code: String) async throws -> [Suggestion] {
12 | guard let apiKey = super.fetchApiKey() else {
13 | throw ConverterError.authorization
14 | }
15 |
16 | let openAI = OpenAI(key: apiKey)
17 |
18 | var suggestions: [Suggestion]?
19 |
20 | do {
21 | let chatpGPTResponse = try await openAI.comment(function: code)
22 |
23 | suggestions = chatpGPTResponse.choices.map { choice in
24 | let suggestion = Suggestion(result: choice.message.content)
25 |
26 | return suggestion
27 | }
28 | } catch ChatGPTError.rateLimitReached {
29 | throw ConverterError.rateLimit
30 | } catch ChatGPTError.serverError {
31 | throw ConverterError.serverStatus
32 | } catch ChatGPTError.authentication {
33 | throw ConverterError.authorization
34 | } catch {
35 | throw ConverterError.unknownResponse
36 | }
37 |
38 | guard let suggestions else {
39 | throw ConverterError.emptyResults
40 | }
41 |
42 | return suggestions
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Data/Repositories/ChatGPTExplainCodeRepository.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ChatGPTExplainCodeRepository.swift
3 | // ChatGPTExtension
4 | //
5 | // Created by Adolfo Vera Blasco on 5/3/23.
6 | //
7 |
8 | import Foundation
9 |
10 | final class ChatGPTExplainCodeRepository: BaseChatGPTRepository, ExplainCodeRepository {
11 | func explainMeThis(code: String) async throws -> [Suggestion] {
12 | guard let apiKey = super.fetchApiKey() else {
13 | throw ConverterError.authorization
14 | }
15 |
16 | let openAI = OpenAI(key: apiKey)
17 |
18 | var suggestions: [Suggestion]?
19 |
20 | do {
21 | let chatpGPTResponse = try await openAI.explain(source: code)
22 |
23 | suggestions = chatpGPTResponse.choices.map { choice in
24 | let suggestion = Suggestion(result: choice.message.content)
25 |
26 | return suggestion
27 | }
28 | } catch ChatGPTError.rateLimitReached {
29 | throw ConverterError.rateLimit
30 | } catch ChatGPTError.serverError {
31 | throw ConverterError.serverStatus
32 | } catch ChatGPTError.authentication {
33 | throw ConverterError.authorization
34 | } catch {
35 | throw ConverterError.unknownResponse
36 | }
37 |
38 | guard let suggestions else {
39 | throw ConverterError.emptyResults
40 | }
41 |
42 | return suggestions
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Data/Repositories/ChatGPTJSONConverterRepository.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ChatGPTAnalyzeRepository.swift
3 | // ChatGPTExtension
4 | //
5 | // Created by Adolfo Vera Blasco on 4/3/23.
6 | //
7 |
8 | import Foundation
9 |
10 | final class ChatGPTJSONConverterRepository: BaseChatGPTRepository, JSONConverterRepository {
11 | func analyze(code: String) async throws -> [Suggestion] {
12 | guard let apiKey = super.fetchApiKey() else {
13 | throw ConverterError.authorization
14 | }
15 |
16 | let openAI = OpenAI(key: apiKey)
17 |
18 | var suggestions: [Suggestion]?
19 |
20 | do {
21 | let chatpGPTResponse = try await openAI.analyze(source: code)
22 |
23 | suggestions = chatpGPTResponse.choices.map { choice in
24 | let suggestion = Suggestion(result: choice.message.content)
25 |
26 | return suggestion
27 | }
28 | } catch ChatGPTError.rateLimitReached {
29 | throw ConverterError.rateLimit
30 | } catch ChatGPTError.serverError {
31 | throw ConverterError.serverStatus
32 | } catch ChatGPTError.authentication {
33 | throw ConverterError.authorization
34 | } catch {
35 | throw ConverterError.unknownResponse
36 | }
37 |
38 | guard let suggestions else {
39 | throw ConverterError.emptyResults
40 | }
41 |
42 | return suggestions
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Data/Repositories/ChatGPTRegexRepository.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ChatGPTRegexRepository.swift
3 | // ChatGPTExtension
4 | //
5 | // Created by Adolfo Vera Blasco on 20/3/23.
6 | //
7 |
8 | import Foundation
9 |
10 | final class ChatGPTRegexRepository: BaseChatGPTRepository, RegexRepository {
11 | func generateRegexFor(string value: String) async throws -> [Suggestion] {
12 | guard let apiKey = super.fetchApiKey() else {
13 | throw ConverterError.authorization
14 | }
15 |
16 | let openAI = OpenAI(key: apiKey)
17 |
18 | var suggestions: [Suggestion]?
19 |
20 | do {
21 | let chatpGPTResponse = try await openAI.generateRegexFor(string: value)
22 |
23 | suggestions = chatpGPTResponse.choices.map { choice in
24 | let suggestion = Suggestion(result: choice.message.content)
25 |
26 | return suggestion
27 | }
28 | } catch ChatGPTError.rateLimitReached {
29 | throw ConverterError.rateLimit
30 | } catch ChatGPTError.serverError {
31 | throw ConverterError.serverStatus
32 | } catch ChatGPTError.authentication {
33 | throw ConverterError.authorization
34 | } catch {
35 | throw ConverterError.unknownResponse
36 | }
37 |
38 | guard let suggestions else {
39 | throw ConverterError.emptyResults
40 | }
41 |
42 | return suggestions
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Data/Repositories/ChatGPTCodeSmellsRepository.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ChatGPTCodeSmellsRepository.swift
3 | // ChatGPTExtension
4 | //
5 | // Created by Adolfo Vera Blasco on 4/3/23.
6 | //
7 |
8 | import Foundation
9 |
10 | final class ChatGPTCodeSmellsRepository: BaseChatGPTRepository, CodeSmellsRepository {
11 | func searchForCodeSmells(in code: String) async throws -> [Suggestion] {
12 | guard let apiKey = super.fetchApiKey() else {
13 | throw ConverterError.authorization
14 | }
15 |
16 | let openAI = OpenAI(key: apiKey)
17 |
18 | var suggestions: [Suggestion]?
19 |
20 | do {
21 | let chatpGPTResponse = try await openAI.codeSmellsFor(code: code)
22 |
23 | suggestions = chatpGPTResponse.choices.map { choice in
24 | let suggestion = Suggestion(result: choice.message.content)
25 |
26 | return suggestion
27 | }
28 | } catch ChatGPTError.rateLimitReached {
29 | throw ConverterError.rateLimit
30 | } catch ChatGPTError.serverError {
31 | throw ConverterError.serverStatus
32 | } catch ChatGPTError.authentication {
33 | throw ConverterError.authorization
34 | } catch {
35 | throw ConverterError.unknownResponse
36 | }
37 |
38 | guard let suggestions else {
39 | throw ConverterError.emptyResults
40 | }
41 |
42 | return suggestions
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Data/Repositories/ChatGPTUnitTestRepository.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ChatGPTUnitTestRepository.swift
3 | // ChatGPTExtension
4 | //
5 | // Created by Adolfo Vera Blasco on 19/3/23.
6 | //
7 |
8 | import Foundation
9 |
10 | final class ChatGPTUnitTestRepository: BaseChatGPTRepository, UnitTestRepository {
11 | func generateTestsFor(source code: String) async throws -> [Suggestion] {
12 | guard let apiKey = super.fetchApiKey() else {
13 | throw ConverterError.authorization
14 | }
15 |
16 | let openAI = OpenAI(key: apiKey)
17 |
18 | var suggestions: [Suggestion]?
19 |
20 | do {
21 | let chatpGPTResponse = try await openAI.generateTestsFor(source: code)
22 |
23 | suggestions = chatpGPTResponse.choices.map { choice in
24 | let suggestion = Suggestion(result: choice.message.content)
25 |
26 | return suggestion
27 | }
28 | } catch ChatGPTError.rateLimitReached {
29 | throw ConverterError.rateLimit
30 | } catch ChatGPTError.serverError {
31 | throw ConverterError.serverStatus
32 | } catch ChatGPTError.authentication {
33 | throw ConverterError.authorization
34 | } catch {
35 | throw ConverterError.unknownResponse
36 | }
37 |
38 | guard let suggestions else {
39 | throw ConverterError.emptyResults
40 | }
41 |
42 | return suggestions
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Data/Network/OpenAI/OpenAI+Operations.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OpenAI+Operations.swift
3 | // ChatGPTExtension
4 | //
5 | // Created by Adolfo Vera Blasco on 5/3/23.
6 | //
7 |
8 | import Foundation
9 |
10 | extension OpenAI {
11 | func codeSmellsFor(code: String) async throws -> ChatGPTResponse {
12 | let smellsPrompt = "\(localizedPrompt("PROMPT_CODE_SMELLS")) \(code)"
13 |
14 | return try await processRequestFor(prompt: smellsPrompt)
15 | }
16 |
17 | func analyze(source code: String) async throws -> ChatGPTResponse {
18 | let jsonPrompt = "\(localizedPrompt("PROMPT_JSON")) \(code)"
19 |
20 | return try await processRequestFor(prompt: jsonPrompt)
21 | }
22 |
23 | func explain(source code: String) async throws -> ChatGPTResponse {
24 | let explainPrompt = "\(localizedPrompt("PROMPT_EXPLAIN_CODE")) \(code)"
25 |
26 | return try await processRequestFor(prompt: explainPrompt)
27 | }
28 |
29 | func generateTestsFor(source code: String) async throws -> ChatGPTResponse {
30 | let testsPrompt = "\(localizedPrompt("PROMPT_GENERATE_UNIT_TEST")) \(code)"
31 |
32 | return try await processRequestFor(prompt: testsPrompt)
33 | }
34 |
35 | func generateRegexFor(string value: String) async throws -> ChatGPTResponse {
36 | let regexPrompt = "\(localizedPrompt("PROMPT_REGEX")) \(value)"
37 |
38 | return try await processRequestFor(prompt: regexPrompt)
39 | }
40 |
41 | func comment(function code: String) async throws -> ChatGPTResponse {
42 | let commentPrompt = "\(localizedPrompt("PROMPT_COMMENT")) \(code)"
43 |
44 | return try await processRequestFor(prompt: commentPrompt)
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Commands/Comment/CommentCommand.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CommentCommand.swift
3 | // ChatGPTExtension
4 | //
5 | // Created by Adolfo Vera Blasco on 22/3/23.
6 | //
7 |
8 | import Foundation
9 | import XcodeKit
10 |
11 | final class CommentCommand: NSObject, XCSourceEditorCommand {
12 | let useCase: CommentUseCase = DependencyManager.makeCommentDependencies()
13 |
14 | func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: @escaping (Error?) -> Void ) -> Void {
15 | guard let codeLines = invocation.buffer.lines as? [String],
16 | let selections = invocation.buffer.selections as? [XCSourceTextRange],
17 | let xcodeSelection = selections.first
18 | else
19 | {
20 | completionHandler(nil)
21 | return
22 | }
23 |
24 | Task {
25 | do {
26 | let functionLines = extractSelectedTextFrom(selection: xcodeSelection, from: codeLines)
27 | let suggestion = try await self.useCase.comment(function: functionLines)
28 |
29 | let comment = "/**\(suggestion.result)\n*/"
30 |
31 | invocation.buffer.lines.insert(comment, at: xcodeSelection.start.line)
32 | } catch let error {
33 | print("🚨 Something goes wrong... \(error)")
34 | }
35 |
36 | completionHandler(nil)
37 | }
38 | }
39 |
40 | private func extractSelectedTextFrom(selection: XCSourceTextRange, from lines: [String]) -> [String] {
41 | let selectedLinesSlice = lines[selection.start.line..(selectedLinesSlice)
43 |
44 | return selectedLines
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Data/Network/OpenAI/Model/NetworkRequest.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NetworkRequest.swift
3 | // ChatGPTExtension
4 | //
5 | // Created by Adolfo Vera Blasco on 3/3/23.
6 | //
7 |
8 | import Foundation
9 |
10 | public struct NetworkRequest {
11 | // MARK: - HttpMethod enum
12 | /// HTTP Methods
13 | public enum HttpMethod: String {
14 | case get = "GET"
15 | case post = "POST"
16 | case put = "PUT"
17 | case patch = "PATCH"
18 | case delete = "DELETE"
19 | }
20 |
21 | // MARK: - Public properties
22 | /// HTTP headers
23 | public var headers: [String : String]?
24 | /// Information for the HTTP *body*
25 | public var payload: Data?
26 | /// HTTP verb
27 | public var method: NetworkRequest.HttpMethod = .post
28 |
29 | // MARK: - Initializer
30 | public init(httpHeaders: [String : String]? = nil, body payload: Data? = nil, httpMethod: NetworkRequest.HttpMethod = .post) {
31 | self.headers = httpHeaders
32 | self.payload = payload
33 | self.method = httpMethod
34 | }
35 |
36 | // MARK: - Functions
37 | /**
38 | Create an `URLRequest` based on the current parameters
39 | for an endpoint.
40 |
41 | - Parameter endpoint: URL to fetch
42 | - Returns: A new `URLRequest`
43 | */
44 | func makeURLRequest(for endpoint: String) -> URLRequest? {
45 | guard let url = URL(string: endpoint) else {
46 | return nil
47 | }
48 |
49 | var request = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalCacheData)
50 |
51 | if let headers = headers {
52 | headers.forEach({ request.addValue($0.value, forHTTPHeaderField: $0.key) })
53 | }
54 |
55 | if let body = payload {
56 | request.httpBody = body
57 | }
58 |
59 | request.httpMethod = self.method.rawValue
60 |
61 | return request
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Infrastructure/Dependencies/DependencyManager.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DependencyManager.swift
3 | // ChatGPTExtension
4 | //
5 | // Created by Adolfo Vera Blasco on 4/3/23.
6 | //
7 |
8 | import Foundation
9 |
10 | final class DependencyManager {
11 | static func makeAnalyzeDependencies() -> JSONConverterUseCase {
12 | let jsonConverterRepository: JSONConverterRepository = ChatGPTJSONConverterRepository()
13 | let useCase: JSONConverterUseCase = DefaultJSONConverterUseCase(repository: jsonConverterRepository)
14 |
15 | return useCase
16 | }
17 |
18 | static func makeCodeSmellsDependencies() -> CodeSmellsUseCase {
19 | let codeSmellsRepository: CodeSmellsRepository = ChatGPTCodeSmellsRepository()
20 | let useCase: CodeSmellsUseCase = DefaultCodeSmellsUseCase(repository: codeSmellsRepository)
21 |
22 | return useCase
23 | }
24 |
25 | static func makeExplainCodeDependencies() -> ExplainCodeUseCase {
26 | let explainCodeRepository: ExplainCodeRepository = ChatGPTExplainCodeRepository()
27 | let useCase: ExplainCodeUseCase = DefaultExplainCodeUseCase(repository: explainCodeRepository)
28 |
29 | return useCase
30 | }
31 |
32 | static func makeUnitTestsDependencies() -> UnitTestUseCase {
33 | let unitTestRepository: UnitTestRepository = ChatGPTUnitTestRepository()
34 | let useCase: UnitTestUseCase = DefaultUnitTestUseCase(repository: unitTestRepository)
35 |
36 | return useCase
37 | }
38 |
39 | static func makeRegexDependencies() -> RegexUseCase {
40 | let regexRepository: RegexRepository = ChatGPTRegexRepository()
41 | let useCase: RegexUseCase = DefaultRegexUseCase(repository: regexRepository)
42 |
43 | return useCase
44 | }
45 |
46 | static func makeCommentDependencies() -> CommentUseCase {
47 | let commentRepository: CommentRepository = ChatGPTCommentRepository()
48 | let useCase: CommentUseCase = DefaultCommentUseCase(repository: commentRepository)
49 |
50 | return useCase
51 | }
52 | }
53 |
54 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Commands/Regex/RegexCommand.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RegexCommand.swift
3 | // ChatGPTExtension
4 | //
5 | // Created by Adolfo Vera Blasco on 21/3/23.
6 | //
7 |
8 | import Foundation
9 | import XcodeKit
10 |
11 | final class RegexCommand: NSObject, XCSourceEditorCommand {
12 | let useCase: RegexUseCase = DependencyManager.makeRegexDependencies()
13 |
14 | func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: @escaping (Error?) -> Void) {
15 | guard let selections = invocation.buffer.selections as? [XCSourceTextRange],
16 | let lines = invocation.buffer.lines as? [String]
17 | else
18 | {
19 | completionHandler(nil)
20 | return
21 | }
22 |
23 | Task {
24 | do {
25 | let selectedTexts = extractSelections(selections, fromText: lines)
26 |
27 | for selectedText in selectedTexts {
28 | let suggestion = try await self.useCase.generateRegexFor(string: selectedText)
29 |
30 | let suggestedRegex = "/**\(suggestion.result)\n*/"
31 |
32 | invocation.buffer.lines.add(suggestedRegex)
33 | }
34 | } catch let error {
35 | print("🚨 Something goes wrong... \(error)")
36 | }
37 |
38 | completionHandler(nil)
39 | }
40 | }
41 |
42 | private func extractSelections(_ selections: [XCSourceTextRange], fromText lines: [String]) -> [String] {
43 | var selectedLines = [String]()
44 |
45 | for selection in selections where selection.start.line == selection.end.line {
46 | let line = lines[selection.start.line]
47 |
48 | let startIndex = line.index(line.startIndex, offsetBy: selection.start.column)
49 | let endIndex = line.index(line.startIndex, offsetBy: selection.end.column)
50 |
51 | let selectedText = String(line[startIndex.. ChatGPTResponse {
24 | let chatGRTRequest = ChatGPTRequest(prompt: prompt)
25 | let data = try? JSONEncoder().encode(chatGRTRequest)
26 |
27 | let request = NetworkRequest(httpHeaders: commonHeaders, body: data)
28 |
29 | guard let openaiURLRequest = request.makeURLRequest(for: Constants.baseURL) else {
30 | throw ChatGPTError.malformedURL(value: Constants.baseURL)
31 | }
32 |
33 | guard let (data, response) = try? await URLSession.shared.data(for: openaiURLRequest),
34 | let httpResponse = response as? HTTPURLResponse
35 | else
36 | {
37 | throw ChatGPTError.unknownServerResponse
38 | }
39 |
40 | switch httpResponse.statusCode {
41 | case 401:
42 | throw ChatGPTError.authentication
43 | case 429:
44 | throw ChatGPTError.rateLimitReached
45 | case 500:
46 | throw ChatGPTError.serverError
47 | case 200:
48 | let chatGPTResponse = try self.processResponse(data: data)
49 | return chatGPTResponse
50 | default:
51 | throw ChatGPTError.unknownServerResponse
52 | }
53 | }
54 |
55 | private func processResponse(data: Data) throws -> ChatGPTResponse {
56 | let jsonDecoder = JSONDecoder()
57 |
58 | do {
59 | let chatGPTResponse = try jsonDecoder.decode(ChatGPTResponse.self, from: data)
60 | return chatGPTResponse
61 | } catch {
62 | throw ChatGPTError.malformedResponse
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # File system
2 | .DS_Store
3 |
4 | # Avoid environment files
5 | *.environment
6 |
7 | # Xcode
8 | #
9 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
10 |
11 | ## User settings
12 | xcuserdata/
13 |
14 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
15 | *.xcscmblueprint
16 | *.xccheckout
17 |
18 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
19 | build/
20 | DerivedData/
21 | *.moved-aside
22 | *.pbxuser
23 | !default.pbxuser
24 | *.mode1v3
25 | !default.mode1v3
26 | *.mode2v3
27 | !default.mode2v3
28 | *.perspectivev3
29 | !default.perspectivev3
30 |
31 | ## Obj-C/Swift specific
32 | *.hmap
33 |
34 | ## App packaging
35 | *.ipa
36 | *.dSYM.zip
37 | *.dSYM
38 |
39 | ## Playgrounds
40 | timeline.xctimeline
41 | playground.xcworkspace
42 |
43 | # Swift Package Manager
44 | #
45 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
46 | # Packages/
47 | # Package.pins
48 | # Package.resolved
49 | # *.xcodeproj
50 | #
51 | # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata
52 | # hence it is not needed unless you have added a package configuration file to your project
53 | # .swiftpm
54 |
55 | .build/
56 |
57 | # CocoaPods
58 | #
59 | # We recommend against adding the Pods directory to your .gitignore. However
60 | # you should judge for yourself, the pros and cons are mentioned at:
61 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
62 | #
63 | # Pods/
64 | #
65 | # Add this line if you want to avoid checking in source code from the Xcode workspace
66 | # *.xcworkspace
67 |
68 | # Carthage
69 | #
70 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
71 | # Carthage/Checkouts
72 |
73 | Carthage/Build/
74 |
75 | # Accio dependency management
76 | Dependencies/
77 | .accio/
78 |
79 | # fastlane
80 | #
81 | # It is recommended to not store the screenshots in the git repo.
82 | # Instead, use fastlane to re-generate the screenshots whenever they are needed.
83 | # For more information about the recommended setup visit:
84 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
85 |
86 | fastlane/report.xml
87 | fastlane/Preview.html
88 | fastlane/screenshots/**/*.png
89 | fastlane/test_output
90 |
91 | # Code Injection
92 | #
93 | # After new code Injection tools there's a generated folder /iOSInjectionProject
94 | # https://github.com/johnno1962/injectionforxcode
95 |
96 | iOSInjectionProject/
97 |
--------------------------------------------------------------------------------
/ChatGPT.xcodeproj/xcshareddata/xcschemes/ChatGPT.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
45 |
51 |
52 |
53 |
54 |
60 |
62 |
68 |
69 |
70 |
71 |
73 |
74 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/ChatGPTExtension/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NSExtension
6 |
7 | NSExtensionAttributes
8 |
9 | XCSourceEditorCommandDefinitions
10 |
11 |
12 | XCSourceEditorCommandClassName
13 | $(PRODUCT_MODULE_NAME).JSON2SwiftEditorCommand
14 | XCSourceEditorCommandIdentifier
15 | $(PRODUCT_BUNDLE_IDENTIFIER).JSON2SwiftEditorCommand
16 | XCSourceEditorCommandName
17 | JSON to Swift
18 |
19 |
20 |
21 | XCSourceEditorCommandClassName
22 | $(PRODUCT_MODULE_NAME).CodeSmellsEditorCommand
23 | XCSourceEditorCommandIdentifier
24 | $(PRODUCT_BUNDLE_IDENTIFIER).CodeSmellsEditorCommand
25 | XCSourceEditorCommandName
26 | Check for Code Smells
27 |
28 |
29 |
30 | XCSourceEditorCommandClassName
31 | $(PRODUCT_MODULE_NAME).ExplainCodeCommand
32 | XCSourceEditorCommandIdentifier
33 | $(PRODUCT_BUNDLE_IDENTIFIER).ExplainCodeCommand
34 | XCSourceEditorCommandName
35 | Explain me this code
36 |
37 |
38 |
39 | XCSourceEditorCommandClassName
40 | $(PRODUCT_MODULE_NAME).UnitTestEditorCommand
41 | XCSourceEditorCommandIdentifier
42 | $(PRODUCT_BUNDLE_IDENTIFIER).UnitTestEditorCommand
43 | XCSourceEditorCommandName
44 | Generate tests for this function
45 |
46 |
47 |
48 | XCSourceEditorCommandClassName
49 | $(PRODUCT_MODULE_NAME).RegexCommand
50 | XCSourceEditorCommandIdentifier
51 | $(PRODUCT_BUNDLE_IDENTIFIER).RegexCommand
52 | XCSourceEditorCommandName
53 | Generate regular expression based on a sample string
54 |
55 |
56 |
57 | XCSourceEditorCommandClassName
58 | $(PRODUCT_MODULE_NAME).CommentCommand
59 | XCSourceEditorCommandIdentifier
60 | $(PRODUCT_BUNDLE_IDENTIFIER).CommentCommand
61 | XCSourceEditorCommandName
62 | Add Swift comments
63 |
64 |
65 |
66 | XCSourceEditorExtensionPrincipalClass
67 | $(PRODUCT_MODULE_NAME).SourceEditorExtension
68 |
69 | NSExtensionPointIdentifier
70 | com.apple.dt.Xcode.extension.source-editor
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/ChatGPT.xcodeproj/xcshareddata/xcschemes/ChatGPTExtension.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
6 |
9 |
10 |
16 |
22 |
23 |
24 |
30 |
36 |
37 |
38 |
39 |
40 |
45 |
46 |
47 |
48 |
60 |
64 |
65 |
66 |
72 |
73 |
74 |
75 |
83 |
85 |
91 |
92 |
93 |
94 |
96 |
97 |
100 |
101 |
102 |
--------------------------------------------------------------------------------
/ChatGPT.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 56;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 911729AD29B32E780066F46E /* DependencyManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 911729AC29B32E780066F46E /* DependencyManager.swift */; };
11 | 911729AF29B32FFB0066F46E /* ChatGPTResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 911729AE29B32FFB0066F46E /* ChatGPTResponse.swift */; };
12 | 9126724629B350320076A294 /* ChatGPTError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9126724529B350320076A294 /* ChatGPTError.swift */; };
13 | 9126724829B359CA0076A294 /* JSONConverterRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9126724729B359CA0076A294 /* JSONConverterRepository.swift */; };
14 | 9126724A29B35A000076A294 /* ChatGPTJSONConverterRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9126724929B35A000076A294 /* ChatGPTJSONConverterRepository.swift */; };
15 | 9134BA4D29CA1E8200784AF2 /* RegexCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9134BA4C29CA1E8200784AF2 /* RegexCommand.swift */; };
16 | 913C1D9229C8D2F300EE95B6 /* RegexRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 913C1D9129C8D2F300EE95B6 /* RegexRepository.swift */; };
17 | 913C1D9429C8D32400EE95B6 /* ChatGPTRegexRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 913C1D9329C8D32400EE95B6 /* ChatGPTRegexRepository.swift */; };
18 | 91893E8B29C7BE8E00AFF495 /* UnitTestEditorCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91893E8A29C7BE8E00AFF495 /* UnitTestEditorCommand.swift */; };
19 | 91893E8E29C7BFD000AFF495 /* UnitTestUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91893E8D29C7BFD000AFF495 /* UnitTestUseCase.swift */; };
20 | 91893E9029C7C01800AFF495 /* DefaultUnitTestUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91893E8F29C7C01800AFF495 /* DefaultUnitTestUseCase.swift */; };
21 | 91893E9229C7C07500AFF495 /* UnitTestRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91893E9129C7C07500AFF495 /* UnitTestRepository.swift */; };
22 | 91893E9429C7C0AC00AFF495 /* ChatGPTUnitTestRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91893E9329C7C0AC00AFF495 /* ChatGPTUnitTestRepository.swift */; };
23 | 91A043D629B48CB60077238E /* OpenAI+Operations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91A043D529B48CB60077238E /* OpenAI+Operations.swift */; };
24 | 91B2577329C8D7C900E11003 /* RegexUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91B2577229C8D7C900E11003 /* RegexUseCase.swift */; };
25 | 91B2577529C8D85600E11003 /* DefaultRegexUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91B2577429C8D85600E11003 /* DefaultRegexUseCase.swift */; };
26 | 91BCF70629B3C18E00C022E9 /* XcodeKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 91FFEE6729B2824B00B4DE2A /* XcodeKit.framework */; };
27 | 91BCF70729B3C18E00C022E9 /* XcodeKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 91FFEE6729B2824B00B4DE2A /* XcodeKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
28 | 91CD167A29B3F1EF0018CA5A /* CodeSmellsEditorCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91CD167929B3F1EF0018CA5A /* CodeSmellsEditorCommand.swift */; };
29 | 91CD167C29B3F35B0018CA5A /* CodeSmellsUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91CD167B29B3F35B0018CA5A /* CodeSmellsUseCase.swift */; };
30 | 91CD167E29B3F39C0018CA5A /* DefaultCodeSmellsUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91CD167D29B3F39C0018CA5A /* DefaultCodeSmellsUseCase.swift */; };
31 | 91CD168029B3F50C0018CA5A /* CodeSmellsRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91CD167F29B3F50C0018CA5A /* CodeSmellsRepository.swift */; };
32 | 91CD168229B3F5410018CA5A /* ChatGPTCodeSmellsRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91CD168129B3F5410018CA5A /* ChatGPTCodeSmellsRepository.swift */; };
33 | 91CD168429B3F7970018CA5A /* BaseChatGPTRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91CD168329B3F7970018CA5A /* BaseChatGPTRepository.swift */; };
34 | 91E2684A29B39ACC0098BBB5 /* JSONConverterUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91E2684929B39ACC0098BBB5 /* JSONConverterUseCase.swift */; };
35 | 91E2684C29B39B6F0098BBB5 /* DefaultJSONConverterUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91E2684B29B39B6F0098BBB5 /* DefaultJSONConverterUseCase.swift */; };
36 | 91E2684E29B3A7510098BBB5 /* Suggestion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91E2684D29B3A7510098BBB5 /* Suggestion.swift */; };
37 | 91E2685329B3AA2C0098BBB5 /* ChatGPTRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91E2685229B3AA2C0098BBB5 /* ChatGPTRequest.swift */; };
38 | 91E2685629B3AC820098BBB5 /* OpenAI+Localizable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91E2685529B3AC820098BBB5 /* OpenAI+Localizable.swift */; };
39 | 91E2685729B3ADDE0098BBB5 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 91E2685929B3ADDE0098BBB5 /* Localizable.strings */; };
40 | 91E2685C29B3B3C50098BBB5 /* ConverterError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91E2685B29B3B3C50098BBB5 /* ConverterError.swift */; };
41 | 91FAD36E29B4784800917E35 /* ExplainCodeCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91FAD36D29B4784800917E35 /* ExplainCodeCommand.swift */; };
42 | 91FAD37029B478A000917E35 /* ExplainCodeUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91FAD36F29B478A000917E35 /* ExplainCodeUseCase.swift */; };
43 | 91FAD37229B478FD00917E35 /* DefaultExplainCodeUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91FAD37129B478FD00917E35 /* DefaultExplainCodeUseCase.swift */; };
44 | 91FAD37429B4796600917E35 /* ExplainCodeRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91FAD37329B4796600917E35 /* ExplainCodeRepository.swift */; };
45 | 91FAD37629B47AEA00917E35 /* ChatGPTExplainCodeRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91FAD37529B47AEA00917E35 /* ChatGPTExplainCodeRepository.swift */; };
46 | 91FFEE5129B2822000B4DE2A /* ChatGPTApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91FFEE5029B2822000B4DE2A /* ChatGPTApp.swift */; };
47 | 91FFEE5329B2822000B4DE2A /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91FFEE5229B2822000B4DE2A /* ContentView.swift */; };
48 | 91FFEE5529B2822100B4DE2A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 91FFEE5429B2822100B4DE2A /* Assets.xcassets */; };
49 | 91FFEE5829B2822100B4DE2A /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 91FFEE5729B2822100B4DE2A /* Preview Assets.xcassets */; };
50 | 91FFEE6629B2824B00B4DE2A /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 91FFEE6529B2824B00B4DE2A /* Cocoa.framework */; };
51 | 91FFEE6B29B2824B00B4DE2A /* SourceEditorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91FFEE6A29B2824B00B4DE2A /* SourceEditorExtension.swift */; };
52 | 91FFEE6D29B2824B00B4DE2A /* JSON2SwiftEditorCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91FFEE6C29B2824B00B4DE2A /* JSON2SwiftEditorCommand.swift */; };
53 | 91FFEE7229B2824B00B4DE2A /* ChatGPTExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 91FFEE6329B2824B00B4DE2A /* ChatGPTExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
54 | 91FFEE7C29B2838000B4DE2A /* OpenAI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91FFEE7B29B2838000B4DE2A /* OpenAI.swift */; };
55 | 91FFEE7F29B2854200B4DE2A /* NetworkRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91FFEE7E29B2854200B4DE2A /* NetworkRequest.swift */; };
56 | 91FFEE8329B288F000B4DE2A /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91FFEE8229B288F000B4DE2A /* Constants.swift */; };
57 | D8E6234C29CB93690072A861 /* openai.environment in Resources */ = {isa = PBXBuildFile; fileRef = D8E6234B29CB93690072A861 /* openai.environment */; };
58 | D8E6234F29CBA0530072A861 /* CommentRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8E6234E29CBA0530072A861 /* CommentRepository.swift */; };
59 | D8E6235129CBA08C0072A861 /* ChatGPTCommentRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8E6235029CBA08C0072A861 /* ChatGPTCommentRepository.swift */; };
60 | D8E6235429CBA1120072A861 /* CommentUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8E6235329CBA1120072A861 /* CommentUseCase.swift */; };
61 | D8E6235629CBA1580072A861 /* DefaultCommentUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8E6235529CBA1580072A861 /* DefaultCommentUseCase.swift */; };
62 | D8E6235929CBA20E0072A861 /* CommentCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8E6235829CBA20E0072A861 /* CommentCommand.swift */; };
63 | /* End PBXBuildFile section */
64 |
65 | /* Begin PBXContainerItemProxy section */
66 | 91FFEE7029B2824B00B4DE2A /* PBXContainerItemProxy */ = {
67 | isa = PBXContainerItemProxy;
68 | containerPortal = 91FFEE4529B2822000B4DE2A /* Project object */;
69 | proxyType = 1;
70 | remoteGlobalIDString = 91FFEE6229B2824B00B4DE2A;
71 | remoteInfo = ChatGPTExtension;
72 | };
73 | /* End PBXContainerItemProxy section */
74 |
75 | /* Begin PBXCopyFilesBuildPhase section */
76 | 91BCF70829B3C18E00C022E9 /* Embed Frameworks */ = {
77 | isa = PBXCopyFilesBuildPhase;
78 | buildActionMask = 2147483647;
79 | dstPath = "";
80 | dstSubfolderSpec = 10;
81 | files = (
82 | 91BCF70729B3C18E00C022E9 /* XcodeKit.framework in Embed Frameworks */,
83 | );
84 | name = "Embed Frameworks";
85 | runOnlyForDeploymentPostprocessing = 0;
86 | };
87 | 91FFEE7629B2824B00B4DE2A /* Embed Foundation Extensions */ = {
88 | isa = PBXCopyFilesBuildPhase;
89 | buildActionMask = 2147483647;
90 | dstPath = "";
91 | dstSubfolderSpec = 13;
92 | files = (
93 | 91FFEE7229B2824B00B4DE2A /* ChatGPTExtension.appex in Embed Foundation Extensions */,
94 | );
95 | name = "Embed Foundation Extensions";
96 | runOnlyForDeploymentPostprocessing = 0;
97 | };
98 | /* End PBXCopyFilesBuildPhase section */
99 |
100 | /* Begin PBXFileReference section */
101 | 911729AC29B32E780066F46E /* DependencyManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DependencyManager.swift; sourceTree = ""; };
102 | 911729AE29B32FFB0066F46E /* ChatGPTResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatGPTResponse.swift; sourceTree = ""; };
103 | 9126724529B350320076A294 /* ChatGPTError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatGPTError.swift; sourceTree = ""; };
104 | 9126724729B359CA0076A294 /* JSONConverterRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSONConverterRepository.swift; sourceTree = ""; };
105 | 9126724929B35A000076A294 /* ChatGPTJSONConverterRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatGPTJSONConverterRepository.swift; sourceTree = ""; };
106 | 9134BA4C29CA1E8200784AF2 /* RegexCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RegexCommand.swift; sourceTree = ""; };
107 | 913C1D9129C8D2F300EE95B6 /* RegexRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RegexRepository.swift; sourceTree = ""; };
108 | 913C1D9329C8D32400EE95B6 /* ChatGPTRegexRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatGPTRegexRepository.swift; sourceTree = ""; };
109 | 91893E8A29C7BE8E00AFF495 /* UnitTestEditorCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnitTestEditorCommand.swift; sourceTree = ""; };
110 | 91893E8D29C7BFD000AFF495 /* UnitTestUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnitTestUseCase.swift; sourceTree = ""; };
111 | 91893E8F29C7C01800AFF495 /* DefaultUnitTestUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultUnitTestUseCase.swift; sourceTree = ""; };
112 | 91893E9129C7C07500AFF495 /* UnitTestRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnitTestRepository.swift; sourceTree = ""; };
113 | 91893E9329C7C0AC00AFF495 /* ChatGPTUnitTestRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatGPTUnitTestRepository.swift; sourceTree = ""; };
114 | 91A043D529B48CB60077238E /* OpenAI+Operations.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OpenAI+Operations.swift"; sourceTree = ""; };
115 | 91B2577229C8D7C900E11003 /* RegexUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RegexUseCase.swift; sourceTree = ""; };
116 | 91B2577429C8D85600E11003 /* DefaultRegexUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultRegexUseCase.swift; sourceTree = ""; };
117 | 91CD167929B3F1EF0018CA5A /* CodeSmellsEditorCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodeSmellsEditorCommand.swift; sourceTree = ""; };
118 | 91CD167B29B3F35B0018CA5A /* CodeSmellsUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodeSmellsUseCase.swift; sourceTree = ""; };
119 | 91CD167D29B3F39C0018CA5A /* DefaultCodeSmellsUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultCodeSmellsUseCase.swift; sourceTree = ""; };
120 | 91CD167F29B3F50C0018CA5A /* CodeSmellsRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodeSmellsRepository.swift; sourceTree = ""; };
121 | 91CD168129B3F5410018CA5A /* ChatGPTCodeSmellsRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatGPTCodeSmellsRepository.swift; sourceTree = ""; };
122 | 91CD168329B3F7970018CA5A /* BaseChatGPTRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseChatGPTRepository.swift; sourceTree = ""; };
123 | 91E2684929B39ACC0098BBB5 /* JSONConverterUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSONConverterUseCase.swift; sourceTree = ""; };
124 | 91E2684B29B39B6F0098BBB5 /* DefaultJSONConverterUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultJSONConverterUseCase.swift; sourceTree = ""; };
125 | 91E2684D29B3A7510098BBB5 /* Suggestion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Suggestion.swift; sourceTree = ""; };
126 | 91E2685229B3AA2C0098BBB5 /* ChatGPTRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatGPTRequest.swift; sourceTree = ""; };
127 | 91E2685529B3AC820098BBB5 /* OpenAI+Localizable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OpenAI+Localizable.swift"; sourceTree = ""; };
128 | 91E2685829B3ADDE0098BBB5 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; };
129 | 91E2685A29B3ADE30098BBB5 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = ""; };
130 | 91E2685B29B3B3C50098BBB5 /* ConverterError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConverterError.swift; sourceTree = ""; };
131 | 91FAD36D29B4784800917E35 /* ExplainCodeCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExplainCodeCommand.swift; sourceTree = ""; };
132 | 91FAD36F29B478A000917E35 /* ExplainCodeUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExplainCodeUseCase.swift; sourceTree = ""; };
133 | 91FAD37129B478FD00917E35 /* DefaultExplainCodeUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultExplainCodeUseCase.swift; sourceTree = ""; };
134 | 91FAD37329B4796600917E35 /* ExplainCodeRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExplainCodeRepository.swift; sourceTree = ""; };
135 | 91FAD37529B47AEA00917E35 /* ChatGPTExplainCodeRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatGPTExplainCodeRepository.swift; sourceTree = ""; };
136 | 91FFEE4D29B2822000B4DE2A /* ChatGPT.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ChatGPT.app; sourceTree = BUILT_PRODUCTS_DIR; };
137 | 91FFEE5029B2822000B4DE2A /* ChatGPTApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatGPTApp.swift; sourceTree = ""; };
138 | 91FFEE5229B2822000B4DE2A /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; };
139 | 91FFEE5429B2822100B4DE2A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
140 | 91FFEE5729B2822100B4DE2A /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; };
141 | 91FFEE5929B2822100B4DE2A /* ChatGPT.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ChatGPT.entitlements; sourceTree = ""; };
142 | 91FFEE6329B2824B00B4DE2A /* ChatGPTExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = ChatGPTExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
143 | 91FFEE6529B2824B00B4DE2A /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
144 | 91FFEE6729B2824B00B4DE2A /* XcodeKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XcodeKit.framework; path = Library/Frameworks/XcodeKit.framework; sourceTree = DEVELOPER_DIR; };
145 | 91FFEE6A29B2824B00B4DE2A /* SourceEditorExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceEditorExtension.swift; sourceTree = ""; };
146 | 91FFEE6C29B2824B00B4DE2A /* JSON2SwiftEditorCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSON2SwiftEditorCommand.swift; sourceTree = ""; };
147 | 91FFEE6E29B2824B00B4DE2A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
148 | 91FFEE6F29B2824B00B4DE2A /* ChatGPTExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ChatGPTExtension.entitlements; sourceTree = ""; };
149 | 91FFEE7B29B2838000B4DE2A /* OpenAI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenAI.swift; sourceTree = ""; };
150 | 91FFEE7E29B2854200B4DE2A /* NetworkRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkRequest.swift; sourceTree = ""; };
151 | 91FFEE8229B288F000B4DE2A /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = ""; };
152 | D8E6234B29CB93690072A861 /* openai.environment */ = {isa = PBXFileReference; lastKnownFileType = text; path = openai.environment; sourceTree = ""; };
153 | D8E6234E29CBA0530072A861 /* CommentRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommentRepository.swift; sourceTree = ""; };
154 | D8E6235029CBA08C0072A861 /* ChatGPTCommentRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatGPTCommentRepository.swift; sourceTree = ""; };
155 | D8E6235329CBA1120072A861 /* CommentUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommentUseCase.swift; sourceTree = ""; };
156 | D8E6235529CBA1580072A861 /* DefaultCommentUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultCommentUseCase.swift; sourceTree = ""; };
157 | D8E6235829CBA20E0072A861 /* CommentCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommentCommand.swift; sourceTree = ""; };
158 | /* End PBXFileReference section */
159 |
160 | /* Begin PBXFrameworksBuildPhase section */
161 | 91FFEE4A29B2822000B4DE2A /* Frameworks */ = {
162 | isa = PBXFrameworksBuildPhase;
163 | buildActionMask = 2147483647;
164 | files = (
165 | );
166 | runOnlyForDeploymentPostprocessing = 0;
167 | };
168 | 91FFEE6029B2824B00B4DE2A /* Frameworks */ = {
169 | isa = PBXFrameworksBuildPhase;
170 | buildActionMask = 2147483647;
171 | files = (
172 | 91FFEE6629B2824B00B4DE2A /* Cocoa.framework in Frameworks */,
173 | 91BCF70629B3C18E00C022E9 /* XcodeKit.framework in Frameworks */,
174 | );
175 | runOnlyForDeploymentPostprocessing = 0;
176 | };
177 | /* End PBXFrameworksBuildPhase section */
178 |
179 | /* Begin PBXGroup section */
180 | 911729A629B32E0D0066F46E /* Domain */ = {
181 | isa = PBXGroup;
182 | children = (
183 | 911729A929B32E2C0066F46E /* Repositories */,
184 | 911729A829B32E230066F46E /* UseCase */,
185 | 911729A729B32E180066F46E /* Model */,
186 | );
187 | path = Domain;
188 | sourceTree = "";
189 | };
190 | 911729A729B32E180066F46E /* Model */ = {
191 | isa = PBXGroup;
192 | children = (
193 | 91E2684D29B3A7510098BBB5 /* Suggestion.swift */,
194 | 91E2685B29B3B3C50098BBB5 /* ConverterError.swift */,
195 | );
196 | path = Model;
197 | sourceTree = "";
198 | };
199 | 911729A829B32E230066F46E /* UseCase */ = {
200 | isa = PBXGroup;
201 | children = (
202 | D8E6235229CBA0FE0072A861 /* Comments */,
203 | 91B2577129C8D7B700E11003 /* Regex */,
204 | 91893E8C29C7BFB500AFF495 /* UnitTest */,
205 | 91AE7F6F29B48BB20037466B /* ExplainCode */,
206 | 91AE7F6E29B48BA70037466B /* CodeSmells */,
207 | 91AE7F6D29B48B970037466B /* JSON2Swift */,
208 | );
209 | path = UseCase;
210 | sourceTree = "";
211 | };
212 | 911729A929B32E2C0066F46E /* Repositories */ = {
213 | isa = PBXGroup;
214 | children = (
215 | 9126724729B359CA0076A294 /* JSONConverterRepository.swift */,
216 | 91CD167F29B3F50C0018CA5A /* CodeSmellsRepository.swift */,
217 | 91FAD37329B4796600917E35 /* ExplainCodeRepository.swift */,
218 | 91893E9129C7C07500AFF495 /* UnitTestRepository.swift */,
219 | 913C1D9129C8D2F300EE95B6 /* RegexRepository.swift */,
220 | D8E6234E29CBA0530072A861 /* CommentRepository.swift */,
221 | );
222 | path = Repositories;
223 | sourceTree = "";
224 | };
225 | 911729AA29B32E580066F46E /* Infrastructure */ = {
226 | isa = PBXGroup;
227 | children = (
228 | 911729AB29B32E670066F46E /* Dependencies */,
229 | );
230 | path = Infrastructure;
231 | sourceTree = "";
232 | };
233 | 911729AB29B32E670066F46E /* Dependencies */ = {
234 | isa = PBXGroup;
235 | children = (
236 | 911729AC29B32E780066F46E /* DependencyManager.swift */,
237 | );
238 | path = Dependencies;
239 | sourceTree = "";
240 | };
241 | 9134BA4B29CA1C9100784AF2 /* Regex */ = {
242 | isa = PBXGroup;
243 | children = (
244 | 9134BA4C29CA1E8200784AF2 /* RegexCommand.swift */,
245 | );
246 | path = Regex;
247 | sourceTree = "";
248 | };
249 | 91893E8929C7BE3D00AFF495 /* UnitTest */ = {
250 | isa = PBXGroup;
251 | children = (
252 | 91893E8A29C7BE8E00AFF495 /* UnitTestEditorCommand.swift */,
253 | );
254 | path = UnitTest;
255 | sourceTree = "";
256 | };
257 | 91893E8C29C7BFB500AFF495 /* UnitTest */ = {
258 | isa = PBXGroup;
259 | children = (
260 | 91893E8D29C7BFD000AFF495 /* UnitTestUseCase.swift */,
261 | 91893E8F29C7C01800AFF495 /* DefaultUnitTestUseCase.swift */,
262 | );
263 | path = UnitTest;
264 | sourceTree = "";
265 | };
266 | 91AE7F6D29B48B970037466B /* JSON2Swift */ = {
267 | isa = PBXGroup;
268 | children = (
269 | 91E2684929B39ACC0098BBB5 /* JSONConverterUseCase.swift */,
270 | 91E2684B29B39B6F0098BBB5 /* DefaultJSONConverterUseCase.swift */,
271 | );
272 | path = JSON2Swift;
273 | sourceTree = "";
274 | };
275 | 91AE7F6E29B48BA70037466B /* CodeSmells */ = {
276 | isa = PBXGroup;
277 | children = (
278 | 91CD167B29B3F35B0018CA5A /* CodeSmellsUseCase.swift */,
279 | 91CD167D29B3F39C0018CA5A /* DefaultCodeSmellsUseCase.swift */,
280 | );
281 | path = CodeSmells;
282 | sourceTree = "";
283 | };
284 | 91AE7F6F29B48BB20037466B /* ExplainCode */ = {
285 | isa = PBXGroup;
286 | children = (
287 | 91FAD36F29B478A000917E35 /* ExplainCodeUseCase.swift */,
288 | 91FAD37129B478FD00917E35 /* DefaultExplainCodeUseCase.swift */,
289 | );
290 | path = ExplainCode;
291 | sourceTree = "";
292 | };
293 | 91B2577129C8D7B700E11003 /* Regex */ = {
294 | isa = PBXGroup;
295 | children = (
296 | 91B2577229C8D7C900E11003 /* RegexUseCase.swift */,
297 | 91B2577429C8D85600E11003 /* DefaultRegexUseCase.swift */,
298 | );
299 | path = Regex;
300 | sourceTree = "";
301 | };
302 | 91BCF70529B3C0D700C022E9 /* Commands */ = {
303 | isa = PBXGroup;
304 | children = (
305 | D8E6235729CBA1F80072A861 /* Comment */,
306 | 9134BA4B29CA1C9100784AF2 /* Regex */,
307 | 91893E8929C7BE3D00AFF495 /* UnitTest */,
308 | 91FAD36C29B4782E00917E35 /* ExplainCode */,
309 | 91CD167829B3F1A00018CA5A /* CodeSmells */,
310 | 91CD167729B3F1860018CA5A /* JSON2Swift */,
311 | 91FFEE6A29B2824B00B4DE2A /* SourceEditorExtension.swift */,
312 | );
313 | path = Commands;
314 | sourceTree = "";
315 | };
316 | 91CD167729B3F1860018CA5A /* JSON2Swift */ = {
317 | isa = PBXGroup;
318 | children = (
319 | 91FFEE6C29B2824B00B4DE2A /* JSON2SwiftEditorCommand.swift */,
320 | );
321 | path = JSON2Swift;
322 | sourceTree = "";
323 | };
324 | 91CD167829B3F1A00018CA5A /* CodeSmells */ = {
325 | isa = PBXGroup;
326 | children = (
327 | 91CD167929B3F1EF0018CA5A /* CodeSmellsEditorCommand.swift */,
328 | );
329 | path = CodeSmells;
330 | sourceTree = "";
331 | };
332 | 91E2684F29B3A8E40098BBB5 /* Resources */ = {
333 | isa = PBXGroup;
334 | children = (
335 | 91E2685929B3ADDE0098BBB5 /* Localizable.strings */,
336 | );
337 | path = Resources;
338 | sourceTree = "";
339 | };
340 | 91E2685429B3AC4C0098BBB5 /* Extensions */ = {
341 | isa = PBXGroup;
342 | children = (
343 | 91E2685529B3AC820098BBB5 /* OpenAI+Localizable.swift */,
344 | );
345 | path = Extensions;
346 | sourceTree = "";
347 | };
348 | 91FAD36C29B4782E00917E35 /* ExplainCode */ = {
349 | isa = PBXGroup;
350 | children = (
351 | 91FAD36D29B4784800917E35 /* ExplainCodeCommand.swift */,
352 | );
353 | path = ExplainCode;
354 | sourceTree = "";
355 | };
356 | 91FFEE4429B2822000B4DE2A = {
357 | isa = PBXGroup;
358 | children = (
359 | 91FFEE4F29B2822000B4DE2A /* ChatGPT */,
360 | 91FFEE6929B2824B00B4DE2A /* ChatGPTExtension */,
361 | 91FFEE6429B2824B00B4DE2A /* Frameworks */,
362 | 91FFEE4E29B2822000B4DE2A /* Products */,
363 | );
364 | sourceTree = "";
365 | };
366 | 91FFEE4E29B2822000B4DE2A /* Products */ = {
367 | isa = PBXGroup;
368 | children = (
369 | 91FFEE4D29B2822000B4DE2A /* ChatGPT.app */,
370 | 91FFEE6329B2824B00B4DE2A /* ChatGPTExtension.appex */,
371 | );
372 | name = Products;
373 | sourceTree = "";
374 | };
375 | 91FFEE4F29B2822000B4DE2A /* ChatGPT */ = {
376 | isa = PBXGroup;
377 | children = (
378 | 91FFEE5029B2822000B4DE2A /* ChatGPTApp.swift */,
379 | 91FFEE5229B2822000B4DE2A /* ContentView.swift */,
380 | 91FFEE5429B2822100B4DE2A /* Assets.xcassets */,
381 | 91FFEE5929B2822100B4DE2A /* ChatGPT.entitlements */,
382 | 91FFEE5629B2822100B4DE2A /* Preview Content */,
383 | );
384 | path = ChatGPT;
385 | sourceTree = "";
386 | };
387 | 91FFEE5629B2822100B4DE2A /* Preview Content */ = {
388 | isa = PBXGroup;
389 | children = (
390 | 91FFEE5729B2822100B4DE2A /* Preview Assets.xcassets */,
391 | );
392 | path = "Preview Content";
393 | sourceTree = "";
394 | };
395 | 91FFEE6429B2824B00B4DE2A /* Frameworks */ = {
396 | isa = PBXGroup;
397 | children = (
398 | 91FFEE6529B2824B00B4DE2A /* Cocoa.framework */,
399 | 91FFEE6729B2824B00B4DE2A /* XcodeKit.framework */,
400 | );
401 | name = Frameworks;
402 | sourceTree = "";
403 | };
404 | 91FFEE6929B2824B00B4DE2A /* ChatGPTExtension */ = {
405 | isa = PBXGroup;
406 | children = (
407 | 91FFEE6E29B2824B00B4DE2A /* Info.plist */,
408 | 91FFEE6F29B2824B00B4DE2A /* ChatGPTExtension.entitlements */,
409 | 911729AA29B32E580066F46E /* Infrastructure */,
410 | 91FFEE7729B2828E00B4DE2A /* Data */,
411 | 911729A629B32E0D0066F46E /* Domain */,
412 | 91BCF70529B3C0D700C022E9 /* Commands */,
413 | );
414 | path = ChatGPTExtension;
415 | sourceTree = "";
416 | };
417 | 91FFEE7729B2828E00B4DE2A /* Data */ = {
418 | isa = PBXGroup;
419 | children = (
420 | D8E6234D29CB9D1A0072A861 /* Settings */,
421 | 91FFEE7A29B282B700B4DE2A /* Repositories */,
422 | 91FFEE7829B2829900B4DE2A /* Network */,
423 | );
424 | path = Data;
425 | sourceTree = "";
426 | };
427 | 91FFEE7829B2829900B4DE2A /* Network */ = {
428 | isa = PBXGroup;
429 | children = (
430 | 91FFEE7929B282A700B4DE2A /* OpenAI */,
431 | );
432 | path = Network;
433 | sourceTree = "";
434 | };
435 | 91FFEE7929B282A700B4DE2A /* OpenAI */ = {
436 | isa = PBXGroup;
437 | children = (
438 | 91E2685429B3AC4C0098BBB5 /* Extensions */,
439 | 91E2684F29B3A8E40098BBB5 /* Resources */,
440 | 91FFEE7D29B2853400B4DE2A /* Model */,
441 | 91FFEE7B29B2838000B4DE2A /* OpenAI.swift */,
442 | 91A043D529B48CB60077238E /* OpenAI+Operations.swift */,
443 | );
444 | path = OpenAI;
445 | sourceTree = "";
446 | };
447 | 91FFEE7A29B282B700B4DE2A /* Repositories */ = {
448 | isa = PBXGroup;
449 | children = (
450 | 9126724929B35A000076A294 /* ChatGPTJSONConverterRepository.swift */,
451 | 91CD168129B3F5410018CA5A /* ChatGPTCodeSmellsRepository.swift */,
452 | 91CD168329B3F7970018CA5A /* BaseChatGPTRepository.swift */,
453 | 91FAD37529B47AEA00917E35 /* ChatGPTExplainCodeRepository.swift */,
454 | 91893E9329C7C0AC00AFF495 /* ChatGPTUnitTestRepository.swift */,
455 | 913C1D9329C8D32400EE95B6 /* ChatGPTRegexRepository.swift */,
456 | D8E6235029CBA08C0072A861 /* ChatGPTCommentRepository.swift */,
457 | );
458 | path = Repositories;
459 | sourceTree = "";
460 | };
461 | 91FFEE7D29B2853400B4DE2A /* Model */ = {
462 | isa = PBXGroup;
463 | children = (
464 | 9126724529B350320076A294 /* ChatGPTError.swift */,
465 | 91E2685229B3AA2C0098BBB5 /* ChatGPTRequest.swift */,
466 | 911729AE29B32FFB0066F46E /* ChatGPTResponse.swift */,
467 | 91FFEE8229B288F000B4DE2A /* Constants.swift */,
468 | 91FFEE7E29B2854200B4DE2A /* NetworkRequest.swift */,
469 | );
470 | path = Model;
471 | sourceTree = "";
472 | };
473 | D8E6234D29CB9D1A0072A861 /* Settings */ = {
474 | isa = PBXGroup;
475 | children = (
476 | D8E6234B29CB93690072A861 /* openai.environment */,
477 | );
478 | path = Settings;
479 | sourceTree = "";
480 | };
481 | D8E6235229CBA0FE0072A861 /* Comments */ = {
482 | isa = PBXGroup;
483 | children = (
484 | D8E6235329CBA1120072A861 /* CommentUseCase.swift */,
485 | D8E6235529CBA1580072A861 /* DefaultCommentUseCase.swift */,
486 | );
487 | path = Comments;
488 | sourceTree = "";
489 | };
490 | D8E6235729CBA1F80072A861 /* Comment */ = {
491 | isa = PBXGroup;
492 | children = (
493 | D8E6235829CBA20E0072A861 /* CommentCommand.swift */,
494 | );
495 | path = Comment;
496 | sourceTree = "";
497 | };
498 | /* End PBXGroup section */
499 |
500 | /* Begin PBXNativeTarget section */
501 | 91FFEE4C29B2822000B4DE2A /* ChatGPT */ = {
502 | isa = PBXNativeTarget;
503 | buildConfigurationList = 91FFEE5C29B2822100B4DE2A /* Build configuration list for PBXNativeTarget "ChatGPT" */;
504 | buildPhases = (
505 | 91FFEE4929B2822000B4DE2A /* Sources */,
506 | 91FFEE4A29B2822000B4DE2A /* Frameworks */,
507 | 91FFEE4B29B2822000B4DE2A /* Resources */,
508 | 91FFEE7629B2824B00B4DE2A /* Embed Foundation Extensions */,
509 | );
510 | buildRules = (
511 | );
512 | dependencies = (
513 | 91FFEE7129B2824B00B4DE2A /* PBXTargetDependency */,
514 | );
515 | name = ChatGPT;
516 | productName = ChatGPT;
517 | productReference = 91FFEE4D29B2822000B4DE2A /* ChatGPT.app */;
518 | productType = "com.apple.product-type.application";
519 | };
520 | 91FFEE6229B2824B00B4DE2A /* ChatGPTExtension */ = {
521 | isa = PBXNativeTarget;
522 | buildConfigurationList = 91FFEE7329B2824B00B4DE2A /* Build configuration list for PBXNativeTarget "ChatGPTExtension" */;
523 | buildPhases = (
524 | 91FFEE5F29B2824B00B4DE2A /* Sources */,
525 | 91FFEE6029B2824B00B4DE2A /* Frameworks */,
526 | 91FFEE6129B2824B00B4DE2A /* Resources */,
527 | 91BCF70829B3C18E00C022E9 /* Embed Frameworks */,
528 | );
529 | buildRules = (
530 | );
531 | dependencies = (
532 | );
533 | name = ChatGPTExtension;
534 | productName = ChatGPTExtension;
535 | productReference = 91FFEE6329B2824B00B4DE2A /* ChatGPTExtension.appex */;
536 | productType = "com.apple.product-type.xcode-extension";
537 | };
538 | /* End PBXNativeTarget section */
539 |
540 | /* Begin PBXProject section */
541 | 91FFEE4529B2822000B4DE2A /* Project object */ = {
542 | isa = PBXProject;
543 | attributes = {
544 | BuildIndependentTargetsInParallel = 1;
545 | LastSwiftUpdateCheck = 1420;
546 | LastUpgradeCheck = 1420;
547 | TargetAttributes = {
548 | 91FFEE4C29B2822000B4DE2A = {
549 | CreatedOnToolsVersion = 14.2;
550 | };
551 | 91FFEE6229B2824B00B4DE2A = {
552 | CreatedOnToolsVersion = 14.2;
553 | };
554 | };
555 | };
556 | buildConfigurationList = 91FFEE4829B2822000B4DE2A /* Build configuration list for PBXProject "ChatGPT" */;
557 | compatibilityVersion = "Xcode 14.0";
558 | developmentRegion = en;
559 | hasScannedForEncodings = 0;
560 | knownRegions = (
561 | en,
562 | Base,
563 | es,
564 | );
565 | mainGroup = 91FFEE4429B2822000B4DE2A;
566 | productRefGroup = 91FFEE4E29B2822000B4DE2A /* Products */;
567 | projectDirPath = "";
568 | projectRoot = "";
569 | targets = (
570 | 91FFEE4C29B2822000B4DE2A /* ChatGPT */,
571 | 91FFEE6229B2824B00B4DE2A /* ChatGPTExtension */,
572 | );
573 | };
574 | /* End PBXProject section */
575 |
576 | /* Begin PBXResourcesBuildPhase section */
577 | 91FFEE4B29B2822000B4DE2A /* Resources */ = {
578 | isa = PBXResourcesBuildPhase;
579 | buildActionMask = 2147483647;
580 | files = (
581 | 91FFEE5829B2822100B4DE2A /* Preview Assets.xcassets in Resources */,
582 | 91FFEE5529B2822100B4DE2A /* Assets.xcassets in Resources */,
583 | );
584 | runOnlyForDeploymentPostprocessing = 0;
585 | };
586 | 91FFEE6129B2824B00B4DE2A /* Resources */ = {
587 | isa = PBXResourcesBuildPhase;
588 | buildActionMask = 2147483647;
589 | files = (
590 | D8E6234C29CB93690072A861 /* openai.environment in Resources */,
591 | 91E2685729B3ADDE0098BBB5 /* Localizable.strings in Resources */,
592 | );
593 | runOnlyForDeploymentPostprocessing = 0;
594 | };
595 | /* End PBXResourcesBuildPhase section */
596 |
597 | /* Begin PBXSourcesBuildPhase section */
598 | 91FFEE4929B2822000B4DE2A /* Sources */ = {
599 | isa = PBXSourcesBuildPhase;
600 | buildActionMask = 2147483647;
601 | files = (
602 | 91FFEE5329B2822000B4DE2A /* ContentView.swift in Sources */,
603 | 91FFEE5129B2822000B4DE2A /* ChatGPTApp.swift in Sources */,
604 | );
605 | runOnlyForDeploymentPostprocessing = 0;
606 | };
607 | 91FFEE5F29B2824B00B4DE2A /* Sources */ = {
608 | isa = PBXSourcesBuildPhase;
609 | buildActionMask = 2147483647;
610 | files = (
611 | 91FAD37029B478A000917E35 /* ExplainCodeUseCase.swift in Sources */,
612 | D8E6235429CBA1120072A861 /* CommentUseCase.swift in Sources */,
613 | 913C1D9229C8D2F300EE95B6 /* RegexRepository.swift in Sources */,
614 | 91FFEE8329B288F000B4DE2A /* Constants.swift in Sources */,
615 | 91FAD37629B47AEA00917E35 /* ChatGPTExplainCodeRepository.swift in Sources */,
616 | 91E2685C29B3B3C50098BBB5 /* ConverterError.swift in Sources */,
617 | 91CD167A29B3F1EF0018CA5A /* CodeSmellsEditorCommand.swift in Sources */,
618 | 91FFEE7C29B2838000B4DE2A /* OpenAI.swift in Sources */,
619 | 913C1D9429C8D32400EE95B6 /* ChatGPTRegexRepository.swift in Sources */,
620 | 91893E9029C7C01800AFF495 /* DefaultUnitTestUseCase.swift in Sources */,
621 | 91CD168029B3F50C0018CA5A /* CodeSmellsRepository.swift in Sources */,
622 | 91893E8E29C7BFD000AFF495 /* UnitTestUseCase.swift in Sources */,
623 | 9126724A29B35A000076A294 /* ChatGPTJSONConverterRepository.swift in Sources */,
624 | 91CD167E29B3F39C0018CA5A /* DefaultCodeSmellsUseCase.swift in Sources */,
625 | 91A043D629B48CB60077238E /* OpenAI+Operations.swift in Sources */,
626 | 9126724629B350320076A294 /* ChatGPTError.swift in Sources */,
627 | 9134BA4D29CA1E8200784AF2 /* RegexCommand.swift in Sources */,
628 | 91E2684E29B3A7510098BBB5 /* Suggestion.swift in Sources */,
629 | 91FAD37429B4796600917E35 /* ExplainCodeRepository.swift in Sources */,
630 | 91B2577329C8D7C900E11003 /* RegexUseCase.swift in Sources */,
631 | 91CD168229B3F5410018CA5A /* ChatGPTCodeSmellsRepository.swift in Sources */,
632 | D8E6234F29CBA0530072A861 /* CommentRepository.swift in Sources */,
633 | 91E2685329B3AA2C0098BBB5 /* ChatGPTRequest.swift in Sources */,
634 | D8E6235629CBA1580072A861 /* DefaultCommentUseCase.swift in Sources */,
635 | 91FFEE6B29B2824B00B4DE2A /* SourceEditorExtension.swift in Sources */,
636 | 91FAD36E29B4784800917E35 /* ExplainCodeCommand.swift in Sources */,
637 | 91893E9229C7C07500AFF495 /* UnitTestRepository.swift in Sources */,
638 | 91FFEE6D29B2824B00B4DE2A /* JSON2SwiftEditorCommand.swift in Sources */,
639 | 911729AD29B32E780066F46E /* DependencyManager.swift in Sources */,
640 | 91CD168429B3F7970018CA5A /* BaseChatGPTRepository.swift in Sources */,
641 | 91FAD37229B478FD00917E35 /* DefaultExplainCodeUseCase.swift in Sources */,
642 | 9126724829B359CA0076A294 /* JSONConverterRepository.swift in Sources */,
643 | 91B2577529C8D85600E11003 /* DefaultRegexUseCase.swift in Sources */,
644 | D8E6235929CBA20E0072A861 /* CommentCommand.swift in Sources */,
645 | 91E2684C29B39B6F0098BBB5 /* DefaultJSONConverterUseCase.swift in Sources */,
646 | 91E2684A29B39ACC0098BBB5 /* JSONConverterUseCase.swift in Sources */,
647 | 91CD167C29B3F35B0018CA5A /* CodeSmellsUseCase.swift in Sources */,
648 | 91893E8B29C7BE8E00AFF495 /* UnitTestEditorCommand.swift in Sources */,
649 | 91FFEE7F29B2854200B4DE2A /* NetworkRequest.swift in Sources */,
650 | 911729AF29B32FFB0066F46E /* ChatGPTResponse.swift in Sources */,
651 | 91893E9429C7C0AC00AFF495 /* ChatGPTUnitTestRepository.swift in Sources */,
652 | 91E2685629B3AC820098BBB5 /* OpenAI+Localizable.swift in Sources */,
653 | D8E6235129CBA08C0072A861 /* ChatGPTCommentRepository.swift in Sources */,
654 | );
655 | runOnlyForDeploymentPostprocessing = 0;
656 | };
657 | /* End PBXSourcesBuildPhase section */
658 |
659 | /* Begin PBXTargetDependency section */
660 | 91FFEE7129B2824B00B4DE2A /* PBXTargetDependency */ = {
661 | isa = PBXTargetDependency;
662 | target = 91FFEE6229B2824B00B4DE2A /* ChatGPTExtension */;
663 | targetProxy = 91FFEE7029B2824B00B4DE2A /* PBXContainerItemProxy */;
664 | };
665 | /* End PBXTargetDependency section */
666 |
667 | /* Begin PBXVariantGroup section */
668 | 91E2685929B3ADDE0098BBB5 /* Localizable.strings */ = {
669 | isa = PBXVariantGroup;
670 | children = (
671 | 91E2685829B3ADDE0098BBB5 /* en */,
672 | 91E2685A29B3ADE30098BBB5 /* es */,
673 | );
674 | name = Localizable.strings;
675 | sourceTree = "";
676 | };
677 | /* End PBXVariantGroup section */
678 |
679 | /* Begin XCBuildConfiguration section */
680 | 91FFEE5A29B2822100B4DE2A /* Debug */ = {
681 | isa = XCBuildConfiguration;
682 | buildSettings = {
683 | ALWAYS_SEARCH_USER_PATHS = NO;
684 | CLANG_ANALYZER_NONNULL = YES;
685 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
686 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
687 | CLANG_ENABLE_MODULES = YES;
688 | CLANG_ENABLE_OBJC_ARC = YES;
689 | CLANG_ENABLE_OBJC_WEAK = YES;
690 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
691 | CLANG_WARN_BOOL_CONVERSION = YES;
692 | CLANG_WARN_COMMA = YES;
693 | CLANG_WARN_CONSTANT_CONVERSION = YES;
694 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
695 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
696 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
697 | CLANG_WARN_EMPTY_BODY = YES;
698 | CLANG_WARN_ENUM_CONVERSION = YES;
699 | CLANG_WARN_INFINITE_RECURSION = YES;
700 | CLANG_WARN_INT_CONVERSION = YES;
701 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
702 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
703 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
704 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
705 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
706 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
707 | CLANG_WARN_STRICT_PROTOTYPES = YES;
708 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
709 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
710 | CLANG_WARN_UNREACHABLE_CODE = YES;
711 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
712 | COPY_PHASE_STRIP = NO;
713 | DEBUG_INFORMATION_FORMAT = dwarf;
714 | ENABLE_STRICT_OBJC_MSGSEND = YES;
715 | ENABLE_TESTABILITY = YES;
716 | GCC_C_LANGUAGE_STANDARD = gnu11;
717 | GCC_DYNAMIC_NO_PIC = NO;
718 | GCC_NO_COMMON_BLOCKS = YES;
719 | GCC_OPTIMIZATION_LEVEL = 0;
720 | GCC_PREPROCESSOR_DEFINITIONS = (
721 | "DEBUG=1",
722 | "$(inherited)",
723 | );
724 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
725 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
726 | GCC_WARN_UNDECLARED_SELECTOR = YES;
727 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
728 | GCC_WARN_UNUSED_FUNCTION = YES;
729 | GCC_WARN_UNUSED_VARIABLE = YES;
730 | MACOSX_DEPLOYMENT_TARGET = 13.1;
731 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
732 | MTL_FAST_MATH = YES;
733 | ONLY_ACTIVE_ARCH = YES;
734 | SDKROOT = macosx;
735 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
736 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
737 | };
738 | name = Debug;
739 | };
740 | 91FFEE5B29B2822100B4DE2A /* Release */ = {
741 | isa = XCBuildConfiguration;
742 | buildSettings = {
743 | ALWAYS_SEARCH_USER_PATHS = NO;
744 | CLANG_ANALYZER_NONNULL = YES;
745 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
746 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
747 | CLANG_ENABLE_MODULES = YES;
748 | CLANG_ENABLE_OBJC_ARC = YES;
749 | CLANG_ENABLE_OBJC_WEAK = YES;
750 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
751 | CLANG_WARN_BOOL_CONVERSION = YES;
752 | CLANG_WARN_COMMA = YES;
753 | CLANG_WARN_CONSTANT_CONVERSION = YES;
754 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
755 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
756 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
757 | CLANG_WARN_EMPTY_BODY = YES;
758 | CLANG_WARN_ENUM_CONVERSION = YES;
759 | CLANG_WARN_INFINITE_RECURSION = YES;
760 | CLANG_WARN_INT_CONVERSION = YES;
761 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
762 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
763 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
764 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
765 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
766 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
767 | CLANG_WARN_STRICT_PROTOTYPES = YES;
768 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
769 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
770 | CLANG_WARN_UNREACHABLE_CODE = YES;
771 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
772 | COPY_PHASE_STRIP = NO;
773 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
774 | ENABLE_NS_ASSERTIONS = NO;
775 | ENABLE_STRICT_OBJC_MSGSEND = YES;
776 | GCC_C_LANGUAGE_STANDARD = gnu11;
777 | GCC_NO_COMMON_BLOCKS = YES;
778 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
779 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
780 | GCC_WARN_UNDECLARED_SELECTOR = YES;
781 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
782 | GCC_WARN_UNUSED_FUNCTION = YES;
783 | GCC_WARN_UNUSED_VARIABLE = YES;
784 | MACOSX_DEPLOYMENT_TARGET = 13.1;
785 | MTL_ENABLE_DEBUG_INFO = NO;
786 | MTL_FAST_MATH = YES;
787 | SDKROOT = macosx;
788 | SWIFT_COMPILATION_MODE = wholemodule;
789 | SWIFT_OPTIMIZATION_LEVEL = "-O";
790 | };
791 | name = Release;
792 | };
793 | 91FFEE5D29B2822100B4DE2A /* Debug */ = {
794 | isa = XCBuildConfiguration;
795 | buildSettings = {
796 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
797 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
798 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
799 | CODE_SIGN_ENTITLEMENTS = ChatGPT/ChatGPT.entitlements;
800 | "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
801 | CODE_SIGN_STYLE = Automatic;
802 | COMBINE_HIDPI_IMAGES = YES;
803 | CURRENT_PROJECT_VERSION = 1;
804 | DEVELOPMENT_ASSET_PATHS = "\"ChatGPT/Preview Content\"";
805 | DEVELOPMENT_TEAM = P8RCF8HS85;
806 | ENABLE_HARDENED_RUNTIME = YES;
807 | ENABLE_PREVIEWS = YES;
808 | GENERATE_INFOPLIST_FILE = YES;
809 | INFOPLIST_KEY_NSHumanReadableCopyright = "";
810 | LD_RUNPATH_SEARCH_PATHS = (
811 | "$(inherited)",
812 | "@executable_path/../Frameworks",
813 | );
814 | MARKETING_VERSION = 1.0;
815 | PRODUCT_BUNDLE_IDENTIFIER = com.desappstre.ChatGPT;
816 | PRODUCT_NAME = "$(TARGET_NAME)";
817 | SWIFT_EMIT_LOC_STRINGS = YES;
818 | SWIFT_VERSION = 5.0;
819 | };
820 | name = Debug;
821 | };
822 | 91FFEE5E29B2822100B4DE2A /* Release */ = {
823 | isa = XCBuildConfiguration;
824 | buildSettings = {
825 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
826 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
827 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
828 | CODE_SIGN_ENTITLEMENTS = ChatGPT/ChatGPT.entitlements;
829 | "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
830 | CODE_SIGN_STYLE = Automatic;
831 | COMBINE_HIDPI_IMAGES = YES;
832 | CURRENT_PROJECT_VERSION = 1;
833 | DEVELOPMENT_ASSET_PATHS = "\"ChatGPT/Preview Content\"";
834 | DEVELOPMENT_TEAM = P8RCF8HS85;
835 | ENABLE_HARDENED_RUNTIME = YES;
836 | ENABLE_PREVIEWS = YES;
837 | GENERATE_INFOPLIST_FILE = YES;
838 | INFOPLIST_KEY_NSHumanReadableCopyright = "";
839 | LD_RUNPATH_SEARCH_PATHS = (
840 | "$(inherited)",
841 | "@executable_path/../Frameworks",
842 | );
843 | MARKETING_VERSION = 1.0;
844 | PRODUCT_BUNDLE_IDENTIFIER = com.desappstre.ChatGPT;
845 | PRODUCT_NAME = "$(TARGET_NAME)";
846 | SWIFT_EMIT_LOC_STRINGS = YES;
847 | SWIFT_VERSION = 5.0;
848 | };
849 | name = Release;
850 | };
851 | 91FFEE7429B2824B00B4DE2A /* Debug */ = {
852 | isa = XCBuildConfiguration;
853 | buildSettings = {
854 | CODE_SIGN_ENTITLEMENTS = ChatGPTExtension/ChatGPTExtension.entitlements;
855 | "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
856 | CODE_SIGN_STYLE = Automatic;
857 | COMBINE_HIDPI_IMAGES = YES;
858 | CURRENT_PROJECT_VERSION = 1;
859 | DEVELOPMENT_TEAM = P8RCF8HS85;
860 | ENABLE_HARDENED_RUNTIME = YES;
861 | GENERATE_INFOPLIST_FILE = YES;
862 | INFOPLIST_FILE = ChatGPTExtension/Info.plist;
863 | INFOPLIST_KEY_CFBundleDisplayName = ChatGPTExtension;
864 | INFOPLIST_KEY_NSHumanReadableCopyright = "";
865 | LD_RUNPATH_SEARCH_PATHS = (
866 | "$(inherited)",
867 | "@executable_path/../Frameworks",
868 | "@executable_path/../../../../Frameworks",
869 | );
870 | MARKETING_VERSION = 1.0;
871 | PRODUCT_BUNDLE_IDENTIFIER = com.desappstre.ChatGPT.ChatGPTExtension;
872 | PRODUCT_NAME = "$(TARGET_NAME)";
873 | SKIP_INSTALL = YES;
874 | SWIFT_EMIT_LOC_STRINGS = YES;
875 | SWIFT_VERSION = 5.0;
876 | };
877 | name = Debug;
878 | };
879 | 91FFEE7529B2824B00B4DE2A /* Release */ = {
880 | isa = XCBuildConfiguration;
881 | buildSettings = {
882 | CODE_SIGN_ENTITLEMENTS = ChatGPTExtension/ChatGPTExtension.entitlements;
883 | "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
884 | CODE_SIGN_STYLE = Automatic;
885 | COMBINE_HIDPI_IMAGES = YES;
886 | CURRENT_PROJECT_VERSION = 1;
887 | DEVELOPMENT_TEAM = P8RCF8HS85;
888 | ENABLE_HARDENED_RUNTIME = YES;
889 | GENERATE_INFOPLIST_FILE = YES;
890 | INFOPLIST_FILE = ChatGPTExtension/Info.plist;
891 | INFOPLIST_KEY_CFBundleDisplayName = ChatGPTExtension;
892 | INFOPLIST_KEY_NSHumanReadableCopyright = "";
893 | LD_RUNPATH_SEARCH_PATHS = (
894 | "$(inherited)",
895 | "@executable_path/../Frameworks",
896 | "@executable_path/../../../../Frameworks",
897 | );
898 | MARKETING_VERSION = 1.0;
899 | PRODUCT_BUNDLE_IDENTIFIER = com.desappstre.ChatGPT.ChatGPTExtension;
900 | PRODUCT_NAME = "$(TARGET_NAME)";
901 | SKIP_INSTALL = YES;
902 | SWIFT_EMIT_LOC_STRINGS = YES;
903 | SWIFT_VERSION = 5.0;
904 | };
905 | name = Release;
906 | };
907 | /* End XCBuildConfiguration section */
908 |
909 | /* Begin XCConfigurationList section */
910 | 91FFEE4829B2822000B4DE2A /* Build configuration list for PBXProject "ChatGPT" */ = {
911 | isa = XCConfigurationList;
912 | buildConfigurations = (
913 | 91FFEE5A29B2822100B4DE2A /* Debug */,
914 | 91FFEE5B29B2822100B4DE2A /* Release */,
915 | );
916 | defaultConfigurationIsVisible = 0;
917 | defaultConfigurationName = Release;
918 | };
919 | 91FFEE5C29B2822100B4DE2A /* Build configuration list for PBXNativeTarget "ChatGPT" */ = {
920 | isa = XCConfigurationList;
921 | buildConfigurations = (
922 | 91FFEE5D29B2822100B4DE2A /* Debug */,
923 | 91FFEE5E29B2822100B4DE2A /* Release */,
924 | );
925 | defaultConfigurationIsVisible = 0;
926 | defaultConfigurationName = Release;
927 | };
928 | 91FFEE7329B2824B00B4DE2A /* Build configuration list for PBXNativeTarget "ChatGPTExtension" */ = {
929 | isa = XCConfigurationList;
930 | buildConfigurations = (
931 | 91FFEE7429B2824B00B4DE2A /* Debug */,
932 | 91FFEE7529B2824B00B4DE2A /* Release */,
933 | );
934 | defaultConfigurationIsVisible = 0;
935 | defaultConfigurationName = Release;
936 | };
937 | /* End XCConfigurationList section */
938 | };
939 | rootObject = 91FFEE4529B2822000B4DE2A /* Project object */;
940 | }
941 |
--------------------------------------------------------------------------------