diff --git a/API.md b/API.md new file mode 100644 index 0000000..8b265f2 --- /dev/null +++ b/API.md @@ -0,0 +1,278 @@ +# API 문서 + +StarUML C# 확장 프로그램의 API 문서입니다. + +## 📋 목차 + +- [CsharpCodeGenerator](#csharpcodegenerator) +- [CsharpPreferences](#csharppreferences) +- [CodeGenUtils](#codegenutils) +- [명령어 ID](#명령어-id) + +## CsharpCodeGenerator + +C# 코드 생성을 담당하는 메인 클래스입니다. + +### 생성자 + +```javascript +CsharpCodeGenerator(baseModel, basePath) +``` + +**매개변수:** +- `baseModel` (type.UMLPackage): 코드 생성의 기준이 되는 UML 패키지 +- `basePath` (string): 생성된 파일들이 저장될 기본 경로 + +### 주요 메서드 + +#### generate(baseModel, basePath, options) + +UML 모델에서 C# 코드를 생성합니다. + +**매개변수:** +- `baseModel` (type.UMLPackage): 코드 생성 대상 모델 +- `basePath` (string): 출력 경로 +- `options` (Object): 생성 옵션 + +**반환값:** +- `Promise`: 코드 생성 완료 시 resolve되는 Promise + +**옵션 객체:** +```javascript +{ + csharpDoc: boolean, // CsharpDoc 주석 생성 여부 + useTab: boolean, // 탭 사용 여부 + indentSpaces: number // 들여쓰기 스페이스 수 +} +``` + +### 내부 메서드 + +#### writePackage(elem) +패키지를 처리하여 네임스페이스를 생성합니다. + +#### writeClass(elem) +UML 클래스를 C# 클래스로 변환합니다. + +#### writeInterface(elem) +UML 인터페이스를 C# 인터페이스로 변환합니다. + +#### writeEnumeration(elem) +UML 열거형을 C# enum으로 변환합니다. + +#### writeAttribute(attr) +UML 속성을 C# 필드/프로퍼티로 변환합니다. + +#### writeOperation(op) +UML 연산을 C# 메서드로 변환합니다. + +## CsharpPreferences + +사용자 설정을 관리하는 클래스입니다. + +### 설정 항목 + +#### csharp.gen.csharpDoc +- **타입**: Boolean +- **기본값**: true +- **설명**: CsharpDoc XML 주석 생성 여부 + +#### csharp.gen.useTab +- **타입**: Boolean +- **기본값**: false +- **설명**: 들여쓰기에 탭 사용 여부 + +#### csharp.gen.indentSpaces +- **타입**: Number +- **기본값**: 4 +- **설명**: 스페이스 들여쓰기 크기 + +### 메서드 + +#### getId() +설정 ID를 반환합니다. + +**반환값:** +- `string`: "csharp" + +#### getGenOptions() +현재 설정된 코드 생성 옵션을 반환합니다. + +**반환값:** +- `Object`: 코드 생성 옵션 객체 + +## CodeGenUtils + +코드 생성을 위한 유틸리티 클래스들을 제공합니다. + +### CodeWriter + +코드 작성을 도와주는 유틸리티 클래스입니다. + +#### 생성자 + +```javascript +CodeWriter(indentString) +``` + +**매개변수:** +- `indentString` (string): 들여쓰기 문자열 (기본값: 4개 스페이스) + +#### 메서드 + +##### writeLine(line) +한 줄을 작성합니다. + +**매개변수:** +- `line` (string): 작성할 텍스트 + +##### indent() +들여쓰기 레벨을 증가시킵니다. + +##### outdent() +들여쓰기 레벨을 감소시킵니다. + +##### getIndentString() +현재 들여쓰기 문자열을 반환합니다. + +**반환값:** +- `string`: 현재 들여쓰기 문자열 + +##### getData() +작성된 모든 코드를 문자열로 반환합니다. + +**반환값:** +- `string`: 완성된 코드 문자열 + +## 명령어 ID + +확장 프로그램에서 사용하는 명령어 ID들입니다. + +### 상수 + +- `CMD_CSHARP`: "csharp" - 메인 C# 명령어 +- `CMD_CSHARP_GENERATE`: "csharp.generate" - 코드 생성 명령어 +- `CMD_CSHARP_REVERSE`: "csharp.reverse" - 역공학 명령어 (미구현) +- `CMD_CSHARP_CONFIGURE`: "csharp.configure" - 설정 명령어 + +### 명령어 핸들러 + +#### _handleGenerate(base, path, options) +C# 코드 생성을 처리합니다. + +**매개변수:** +- `base` (Element): 기준 모델 (선택사항) +- `path` (string): 출력 경로 (선택사항) +- `options` (Object): 생성 옵션 (선택사항) + +**반환값:** +- `Promise`: 처리 완료 시 resolve되는 Promise + +#### _handleReverse() +역공학을 처리합니다. (현재 미구현) + +#### _handleConfigure() +설정 대화상자를 엽니다. + +## 사용 예시 + +### 프로그래밍 방식으로 코드 생성 + +```javascript +// 모듈 로드 +var CsharpCodeGenerator = require("CsharpCodeGenerator"); +var CsharpPreferences = require("CsharpPreferences"); + +// 옵션 설정 +var options = CsharpPreferences.getGenOptions(); +options.csharpDoc = true; +options.useTab = false; +options.indentSpaces = 4; + +// 코드 생성 +var generator = new CsharpCodeGenerator(baseModel, "/output/path"); +generator.generate(baseModel, "/output/path", options) + .then(function() { + console.log("코드 생성 완료"); + }) + .catch(function(error) { + console.error("코드 생성 실패:", error); + }); +``` + +### 사용자 정의 CodeWriter 사용 + +```javascript +var CodeGenUtils = require("CodeGenUtils"); + +// CodeWriter 생성 +var writer = new CodeGenUtils.CodeWriter(" "); // 4 스페이스 들여쓰기 + +// 코드 작성 +writer.writeLine("public class MyClass"); +writer.writeLine("{"); +writer.indent(); +writer.writeLine("private string name;"); +writer.writeLine(""); +writer.writeLine("public string Name"); +writer.writeLine("{"); +writer.indent(); +writer.writeLine("get { return name; }"); +writer.writeLine("set { name = value; }"); +writer.outdent(); +writer.writeLine("}"); +writer.outdent(); +writer.writeLine("}"); + +// 결과 출력 +console.log(writer.getData()); +``` + +## 확장 및 커스터마이징 + +### 새로운 코드 생성 규칙 추가 + +`CsharpCodeGenerator.js`를 수정하여 새로운 UML 요소나 C# 기능을 지원할 수 있습니다: + +1. 새로운 `write*` 메서드 추가 +2. `generate` 메서드에서 해당 메서드 호출 +3. 필요한 경우 설정 옵션 추가 + +### 새로운 설정 옵션 추가 + +`CsharpPreferences.js`에서 새로운 설정을 추가할 수 있습니다: + +```javascript +"csharp.gen.newOption": { + text: "새 옵션", + description: "새로운 옵션에 대한 설명", + type: "Check", // 또는 "Number", "String" 등 + default: false +} +``` + +## 오류 처리 + +### 일반적인 오류 상황 + +1. **파일 시스템 오류**: 출력 경로에 쓰기 권한이 없는 경우 +2. **모델 오류**: 잘못된 UML 모델이 전달된 경우 +3. **설정 오류**: 잘못된 설정값이 전달된 경우 + +### 오류 처리 방법 + +```javascript +generator.generate(baseModel, basePath, options) + .then(function(result) { + // 성공 처리 + }) + .catch(function(error) { + if (error === FileSystem.USER_CANCELED) { + // 사용자 취소 + } else { + // 기타 오류 처리 + console.error("오류 발생:", error); + } + }); +``` + diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..09b842f --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,386 @@ +# 기여 가이드 + +StarUML C# 확장 프로그램에 기여해주셔서 감사합니다! 이 문서는 프로젝트에 기여하는 방법을 안내합니다. + +## 📋 목차 + +- [기여 방법](#-기여-방법) +- [개발 환경 설정](#-개발-환경-설정) +- [코딩 스타일](#-코딩-스타일) +- [테스트](#-테스트) +- [Pull Request 가이드라인](#-pull-request-가이드라인) +- [이슈 리포팅](#-이슈-리포팅) +- [문서화](#-문서화) + +## 🤝 기여 방법 + +다음과 같은 방법으로 프로젝트에 기여할 수 있습니다: + +- 🐛 **버그 리포트**: 발견한 버그를 이슈로 등록 +- 💡 **기능 제안**: 새로운 기능이나 개선사항 제안 +- 🔧 **코드 기여**: 버그 수정이나 새 기능 구현 +- 📚 **문서 개선**: README, API 문서, 예제 등 개선 +- 🌍 **번역**: 다른 언어로 문서 번역 +- 🧪 **테스트**: 다양한 환경에서 테스트 및 피드백 + +## 🛠️ 개발 환경 설정 + +### 필수 요구사항 + +- StarUML 2.0.0 이상 +- Git +- 텍스트 에디터 (VS Code, Sublime Text 등) + +### 설정 단계 + +1. **저장소 포크 및 클론** + ```bash + git clone https://github.com/YOUR_USERNAME/CSharp.git + cd CSharp + ``` + +2. **개발 브랜치 생성** + ```bash + git checkout -b feature/your-feature-name + ``` + +3. **StarUML 확장 폴더에 링크 생성** + + **Windows:** + ```cmd + mklink /D "%APPDATA%\StarUML\extensions\user\staruml.csharp" "C:\path\to\your\CSharp" + ``` + + **macOS/Linux:** + ```bash + ln -s /path/to/your/CSharp ~/Library/Application\ Support/StarUML/extensions/user/staruml.csharp + ``` + +4. **StarUML에서 확장 로드** + - StarUML 실행 + - `Debug` > `Reload Extensions` 선택 + - 또는 `Ctrl+Shift+F5` (Windows/Linux) / `Cmd+Shift+F5` (macOS) + +### 개발 워크플로우 + +1. 코드 수정 +2. StarUML에서 `Debug` > `Reload Extensions`로 변경사항 로드 +3. 기능 테스트 +4. 필요시 반복 + +## 📝 코딩 스타일 + +### JavaScript 스타일 가이드 + +프로젝트는 다음 코딩 스타일을 따릅니다: + +#### 기본 규칙 + +- **들여쓰기**: 4개 스페이스 사용 +- **세미콜론**: 항상 사용 +- **따옴표**: 문자열에 큰따옴표 사용 +- **변수명**: camelCase 사용 +- **상수**: UPPER_SNAKE_CASE 사용 + +#### 예시 + +```javascript +// 좋은 예 +var myVariable = "hello world"; +var MY_CONSTANT = 42; + +function myFunction(param1, param2) { + if (param1 === "test") { + return param2 + 1; + } + return 0; +} + +// 나쁜 예 +var my_variable='hello world' +var myconstant=42 + +function myfunction(param1,param2){ +if(param1=='test'){ +return param2+1 +} +return 0 +} +``` + +#### JSLint 규칙 + +프로젝트는 JSLint를 사용합니다. 다음 설정을 준수해주세요: + +```javascript +/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50, regexp: true */ +``` + +#### AMD 모듈 패턴 + +모든 모듈은 AMD 패턴을 사용합니다: + +```javascript +define(function (require, exports, module) { + "use strict"; + + // 모듈 의존성 + var Dependency = require("Dependency"); + + // 모듈 구현 + function MyModule() { + // 구현 내용 + } + + // 내보내기 + exports.MyModule = MyModule; +}); +``` + +### 주석 스타일 + +#### JSDoc 주석 + +함수와 클래스에는 JSDoc 주석을 사용합니다: + +```javascript +/** + * 클래스에 대한 설명 + * @constructor + * @param {type.UMLPackage} baseModel 기본 모델 + * @param {string} basePath 기본 경로 + */ +function CsharpCodeGenerator(baseModel, basePath) { + // 구현 +} + +/** + * 메서드에 대한 설명 + * @param {Element} elem UML 요소 + * @return {string} 생성된 코드 + */ +CsharpCodeGenerator.prototype.writeClass = function (elem) { + // 구현 +}; +``` + +#### 인라인 주석 + +복잡한 로직에는 설명 주석을 추가합니다: + +```javascript +// 사용자가 기본 모델을 선택하지 않은 경우 ElementPicker 표시 +if (!base) { + ElementPickerDialog.showDialog("Select a base model to generate codes", null, type.UMLPackage) + .done(function (buttonId, selected) { + // 처리 로직 + }); +} +``` + +## 🧪 테스트 + +### 수동 테스트 + +현재 프로젝트는 자동화된 테스트가 없으므로 수동 테스트를 수행합니다: + +#### 기본 기능 테스트 + +1. **코드 생성 테스트** + - 다양한 UML 클래스 다이어그램 생성 + - `Tools` > `C#` > `Generate Code...` 실행 + - 생성된 C# 코드 확인 + +2. **설정 테스트** + - `Tools` > `C#` > `Configure...` 실행 + - 각 설정 옵션 변경 후 코드 생성 + - 설정이 올바르게 적용되는지 확인 + +3. **다양한 UML 요소 테스트** + - 클래스, 인터페이스, 열거형 + - 상속, 구현, 연관 관계 + - 다양한 가시성 수준 + +#### 테스트 체크리스트 + +- [ ] 기본 클래스 생성 +- [ ] 인터페이스 생성 +- [ ] 열거형 생성 +- [ ] 상속 관계 처리 +- [ ] 구현 관계 처리 +- [ ] 속성 생성 (다양한 타입) +- [ ] 메서드 생성 (다양한 시그니처) +- [ ] CsharpDoc 주석 생성 +- [ ] 들여쓰기 설정 적용 +- [ ] 패키지 구조를 네임스페이스로 변환 + +### 테스트 환경 + +다음 환경에서 테스트해주세요: + +- **운영체제**: Windows, macOS, Linux +- **StarUML 버전**: 2.0.0 이상의 다양한 버전 +- **UML 모델**: 간단한 것부터 복잡한 것까지 + +## 📬 Pull Request 가이드라인 + +### PR 제출 전 체크리스트 + +- [ ] 코드가 프로젝트의 코딩 스타일을 따름 +- [ ] 새로운 기능에 대한 테스트 완료 +- [ ] 기존 기능이 정상 작동함을 확인 +- [ ] 문서 업데이트 (필요한 경우) +- [ ] 커밋 메시지가 명확함 + +### PR 제목 및 설명 + +#### 제목 형식 +``` +[타입] 간단한 설명 + +예시: +[Feature] Add support for generic types +[Fix] Fix namespace generation bug +[Docs] Update API documentation +``` + +#### 설명 템플릿 +```markdown +## 변경사항 +- 변경된 내용을 간단히 설명 + +## 동기 +- 왜 이 변경이 필요한지 설명 + +## 테스트 +- 어떻게 테스트했는지 설명 +- 테스트 결과 + +## 스크린샷 (해당하는 경우) +- 변경사항을 보여주는 스크린샷 + +## 체크리스트 +- [ ] 코딩 스타일 준수 +- [ ] 테스트 완료 +- [ ] 문서 업데이트 +``` + +### 커밋 메시지 가이드라인 + +#### 형식 +``` +[타입] 제목 (50자 이내) + +본문 (필요한 경우, 72자로 줄바꿈) + +- 변경사항 1 +- 변경사항 2 +``` + +#### 타입 +- `feat`: 새로운 기능 +- `fix`: 버그 수정 +- `docs`: 문서 변경 +- `style`: 코드 스타일 변경 (기능 변경 없음) +- `refactor`: 리팩토링 +- `test`: 테스트 추가/수정 +- `chore`: 빌드 프로세스나 도구 변경 + +## 🐛 이슈 리포팅 + +### 버그 리포트 + +버그를 발견했다면 다음 정보를 포함해서 이슈를 등록해주세요: + +#### 템플릿 +```markdown +## 버그 설명 +버그에 대한 명확하고 간단한 설명 + +## 재현 단계 +1. '...' 이동 +2. '...' 클릭 +3. '...' 입력 +4. 오류 발생 + +## 예상 동작 +무엇이 일어날 것으로 예상했는지 + +## 실제 동작 +실제로 무엇이 일어났는지 + +## 환경 +- OS: [예: Windows 10] +- StarUML 버전: [예: 2.8.0] +- 확장 버전: [예: 0.1.0] + +## 추가 정보 +스크린샷, 로그, 기타 관련 정보 +``` + +### 기능 요청 + +새로운 기능을 제안할 때는 다음 정보를 포함해주세요: + +#### 템플릿 +```markdown +## 기능 설명 +제안하는 기능에 대한 명확하고 간단한 설명 + +## 동기 +이 기능이 왜 필요한지, 어떤 문제를 해결하는지 + +## 제안된 해결책 +어떻게 구현할지에 대한 아이디어 + +## 대안 +고려해본 다른 해결책들 + +## 추가 정보 +기타 관련 정보나 스크린샷 +``` + +## 📚 문서화 + +### 문서 기여 + +문서 개선도 중요한 기여입니다: + +- **README.md**: 사용자 가이드 개선 +- **API.md**: API 문서 업데이트 +- **CONTRIBUTING.md**: 기여 가이드 개선 +- **예제 추가**: 사용 예시나 튜토리얼 + +### 문서 작성 가이드라인 + +- 명확하고 간단한 언어 사용 +- 코드 예시 포함 +- 스크린샷이나 다이어그램 활용 +- 다양한 사용자 레벨 고려 (초보자부터 고급자까지) + +## 🌍 번역 + +다른 언어로 문서를 번역하고 싶다면: + +1. 새로운 언어 폴더 생성 (예: `docs/ko/`, `docs/ja/`) +2. 해당 언어로 문서 번역 +3. PR 제출 + +## 📞 도움이 필요한 경우 + +- **GitHub Issues**: 질문이나 도움 요청 +- **이메일**: joon1251@gmail.com +- **토론**: GitHub Discussions (활성화된 경우) + +## 🎉 기여자 인정 + +모든 기여자는 다음과 같이 인정받습니다: + +- README.md의 기여자 섹션에 이름 추가 +- 릴리스 노트에 기여 내용 언급 +- 특별한 기여에 대해서는 별도 감사 표시 + +--- + +**여러분의 기여가 이 프로젝트를 더욱 발전시킵니다. 감사합니다!** 🙏 + diff --git a/CsharpCodeGenerator.js b/CsharpCodeGenerator.js index a3009d5..cb1ec29 100644 --- a/CsharpCodeGenerator.js +++ b/CsharpCodeGenerator.js @@ -36,6 +36,32 @@ define(function (require, exports, module) { var CodeGenUtils = require("CodeGenUtils"); + /** + * Constants for write function types + */ + var WRITE_FUNCTIONS = { + ANNOTATION_TYPE: "writeAnnotationType", + CLASS: "writeClass", + INTERFACE: "writeInterface", + ENUM: "writeEnum" + }; + + /** + * Constants for attribute suffix handling + */ + var ATTRIBUTE_SUFFIX = "Attribute"; + var ATTRIBUTE_SUFFIX_LENGTH = 9; + + /** + * Standard C# using statements + */ + var STANDARD_USINGS = [ + "using System;", + "using System.Collections.Generic;", + "using System.Linq;", + "using System.Text;" + ]; + /** * C# Code Generator * @constructor @@ -70,6 +96,19 @@ define(function (require, exports, module) { } }; + /** + * Write standard C# using statements + * @param {CodeWriter} codeWriter + */ + CsharpCodeGenerator.prototype.writeUsings = function (codeWriter) { + var i, len; + codeWriter.writeLine(); + for (i = 0, len = STANDARD_USINGS.length; i < len; i++) { + codeWriter.writeLine(STANDARD_USINGS[i]); + } + codeWriter.writeLine(); + }; + /** * Generate codes from a given element * @param {type.Model} elem @@ -94,7 +133,6 @@ define(function (require, exports, module) { Async.doSequentially( elem.ownedElements, function (child) { - console.log('package generate'); return self.generate(child, fullPath, options); }, false @@ -111,44 +149,29 @@ define(function (require, exports, module) { // AnnotationType if (isAnnotationType) { - console.log('annotationType generate'); - - console.log(elem.name.substring(elem.name.length-9, elem.name.length)); - - if(elem.name.length<9 ){ - elem.name = elem.name + "Attribute"; - } - else if ( elem.name.substring(elem.name.length-9, elem.name.length) != "Attribute" ){ - elem.name = elem.name + "Attribute"; + // Ensure annotation type name ends with "Attribute" + if (elem.name.length < ATTRIBUTE_SUFFIX_LENGTH) { + elem.name = elem.name + ATTRIBUTE_SUFFIX; + } else if (elem.name.substring(elem.name.length - ATTRIBUTE_SUFFIX_LENGTH, elem.name.length) !== ATTRIBUTE_SUFFIX) { + elem.name = elem.name + ATTRIBUTE_SUFFIX; } fullPath = path + "/" + elem.name + ".cs"; codeWriter = new CodeGenUtils.CodeWriter(this.getIndentString(options)); - codeWriter.writeLine(); - codeWriter.writeLine("using System;"); - codeWriter.writeLine("using System.Collections.Generic;"); - codeWriter.writeLine("using System.Linq;"); - codeWriter.writeLine("using System.Text;"); - codeWriter.writeLine(); + this.writeUsings(codeWriter); // this.writeAnnotationType(codeWriter, elem, options, isAnnotationType); - this.writeNamespace("writeAnnotationType", codeWriter, elem, options, isAnnotationType); + this.writeNamespace(WRITE_FUNCTIONS.ANNOTATION_TYPE, codeWriter, elem, options, isAnnotationType); file = FileSystem.getFileForPath(fullPath); FileUtils.writeText(file, codeWriter.getData(), true).then(result.resolve, result.reject); } // Class else { fullPath = path + "/" + elem.name + ".cs"; - console.log('Class generate' + fullPath); codeWriter = new CodeGenUtils.CodeWriter(this.getIndentString(options)); - codeWriter.writeLine(); - codeWriter.writeLine("using System;"); - codeWriter.writeLine("using System.Collections.Generic;"); - codeWriter.writeLine("using System.Linq;"); - codeWriter.writeLine("using System.Text;"); - codeWriter.writeLine(); + this.writeUsings(codeWriter); // this.writeClass(codeWriter, elem, options, isAnnotationType); - this.writeNamespace("writeClass", codeWriter, elem, options, isAnnotationType); + this.writeNamespace(WRITE_FUNCTIONS.CLASS, codeWriter, elem, options, isAnnotationType); file = FileSystem.getFileForPath(fullPath); FileUtils.writeText(file, codeWriter.getData(), true).then(result.resolve, result.reject); } @@ -156,17 +179,11 @@ define(function (require, exports, module) { // Interface else if (elem instanceof type.UMLInterface) { fullPath = path + "/" + elem.name + ".cs"; - console.log('Interface generate' + fullPath); codeWriter = new CodeGenUtils.CodeWriter(this.getIndentString(options)); - codeWriter.writeLine(); - codeWriter.writeLine("using System;"); - codeWriter.writeLine("using System.Collections.Generic;"); - codeWriter.writeLine("using System.Linq;"); - codeWriter.writeLine("using System.Text;"); - codeWriter.writeLine(); + this.writeUsings(codeWriter); // this.writeInterface(codeWriter, elem, options); - this.writeNamespace("writeInterface", codeWriter, elem, options, isAnnotationType); + this.writeNamespace(WRITE_FUNCTIONS.INTERFACE, codeWriter, elem, options, isAnnotationType); file = FileSystem.getFileForPath(fullPath); FileUtils.writeText(file, codeWriter.getData(), true).then(result.resolve, result.reject); @@ -175,16 +192,15 @@ define(function (require, exports, module) { else if (elem instanceof type.UMLEnumeration) { fullPath = path + "/" + elem.name + ".cs"; codeWriter = new CodeGenUtils.CodeWriter(this.getIndentString(options)); - codeWriter.writeLine(); + this.writeUsings(codeWriter); // this.writeEnum(codeWriter, elem, options); - this.writeNamespace("writeEnum", codeWriter, elem, options, isAnnotationType); + this.writeNamespace(WRITE_FUNCTIONS.ENUM, codeWriter, elem, options, isAnnotationType); file = FileSystem.getFileForPath(fullPath); FileUtils.writeText(file, codeWriter.getData(), true).then(result.resolve, result.reject); } // Others (Nothing generated.) else { - console.log('nothing generate'); result.resolve(); } return result.promise(); @@ -206,16 +222,13 @@ define(function (require, exports, module) { codeWriter.writeLine("namespace " + path + "{"); codeWriter.indent(); } - if(writeFunction == "writeAnnotationType"){ + if (writeFunction === WRITE_FUNCTIONS.ANNOTATION_TYPE) { this.writeAnnotationType(codeWriter, elem, options); - } - else if (writeFunction == "writeClass"){ + } else if (writeFunction === WRITE_FUNCTIONS.CLASS) { this.writeClass(codeWriter, elem, options); - } - else if (writeFunction == "writeInterface"){ + } else if (writeFunction === WRITE_FUNCTIONS.INTERFACE) { this.writeInterface(codeWriter, elem, options); - } - else if (writeFunction == "writeEnum"){ + } else if (writeFunction === WRITE_FUNCTIONS.ENUM) { this.writeEnum(codeWriter, elem, options); } @@ -419,18 +432,15 @@ define(function (require, exports, module) { return (rel instanceof type.UMLAssociation); }); - console.log('association length: ' + associations.length); for (i = 0, len = associations.length; i < len; i++) { var asso = associations[i]; if (asso.end1.reference === elem && asso.end2.navigable === true) { this.writeMemberVariable(codeWriter, asso.end2, options); codeWriter.writeLine(); - console.log('assoc end1'); } else if (asso.end2.reference === elem && asso.end1.navigable === true) { this.writeMemberVariable(codeWriter, asso.end1, options); codeWriter.writeLine(); - console.log('assoc end2'); } } @@ -447,7 +457,6 @@ define(function (require, exports, module) { if (def.stereotype === "annotationType") { this.writeAnnotationType(codeWriter, def, options); } else { - console.log("class in class"); this.writeClass(codeWriter, def, options); } codeWriter.writeLine(); @@ -533,18 +542,15 @@ define(function (require, exports, module) { return (rel instanceof type.UMLAssociation); }); - console.log('association length: ' + associations.length); for (i = 0, len = associations.length; i < len; i++) { var asso = associations[i]; if (asso.end1.reference === elem && asso.end2.navigable === true) { this.writeMemberVariable(codeWriter, asso.end2, options); codeWriter.writeLine(); - console.log('assoc end1'); } else if (asso.end2.reference === elem && asso.end1.navigable === true) { this.writeMemberVariable(codeWriter, asso.end1, options); codeWriter.writeLine(); - console.log('assoc end2'); } } @@ -561,7 +567,6 @@ define(function (require, exports, module) { if (def.stereotype === "annotationType") { this.writeAnnotationType(codeWriter, def, options); } else { - console.log("class in class"); this.writeClass(codeWriter, def, options); } codeWriter.writeLine(); @@ -646,7 +651,7 @@ define(function (require, exports, module) { if (returnParam) { var returnType = this.getType(returnParam); if (returnType === "bool") { - codeWriter.writeLine("return False;"); + codeWriter.writeLine("return false;"); } else if (returnType === "byte" || returnType === "int" || returnType === "sbyte" @@ -777,13 +782,20 @@ define(function (require, exports, module) { var i, len, lines; if (options.csharpDoc && _.isString(text)) { - console.log("write Doc"); lines = text.trim().split("\n"); - codeWriter.writeLine("/**"); - for (i = 0, len = lines.length; i < len; i++) { - codeWriter.writeLine(" * " + lines[i]); + if (lines.length === 1) { + // Single line summary + codeWriter.writeLine("/// "); + codeWriter.writeLine("/// " + lines[0]); + codeWriter.writeLine("/// "); + } else { + // Multi-line documentation + codeWriter.writeLine("/// "); + for (i = 0, len = lines.length; i < len; i++) { + codeWriter.writeLine("/// " + lines[i]); + } + codeWriter.writeLine("/// "); } - codeWriter.writeLine(" */"); } }; @@ -875,4 +887,4 @@ define(function (require, exports, module) { exports.generate = generate; -}); \ No newline at end of file +}); diff --git a/README.md b/README.md index 92c8d90..32f8ee5 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,217 @@ -CSharp -====== +# C# Extension for StarUML 2 + +StarUML 2용 C# 코드 생성 및 역공학 확장 프로그램입니다. UML 다이어그램에서 C# 코드를 자동으로 생성할 수 있습니다. + +## 📋 목차 + +- [기능](#-기능) +- [설치](#-설치) +- [사용법](#-사용법) +- [설정](#-설정) +- [지원하는 UML 요소](#-지원하는-uml-요소) +- [생성되는 C# 코드 예시](#-생성되는-c-코드-예시) +- [개발자 정보](#-개발자-정보) +- [라이선스](#-라이선스) + +## ✨ 기능 + +- **C# 코드 생성**: UML 클래스 다이어그램에서 C# 클래스, 인터페이스, 열거형 등을 자동 생성 +- **CsharpDoc 주석 생성**: 코드와 함께 XML 문서 주석 자동 생성 +- **사용자 정의 설정**: 들여쓰기, 탭/스페이스 선택 등 코드 스타일 커스터마이징 +- **패키지 구조 지원**: UML 패키지 구조를 네임스페이스로 변환 +- **역공학 지원**: C# 코드에서 UML 다이어그램 생성 (개발 예정) + +## 🚀 설치 + +### 요구사항 +- StarUML 2.0.0 이상 + +### 설치 방법 + +1. **Extension Manager를 통한 설치** (권장) + - StarUML에서 `Tools` > `Extension Manager` 선택 + - `Registry` 탭에서 "C#" 검색 + - `Install` 버튼 클릭 + +2. **수동 설치** + - 이 저장소를 다운로드하거나 클론 + - StarUML 확장 폴더에 복사: + - Windows: `%APPDATA%\StarUML\extensions\user\staruml.csharp` + - macOS: `~/Library/Application Support/StarUML/extensions/user/staruml.csharp` + - Linux: `~/.config/StarUML/extensions/user/staruml.csharp` + - StarUML 재시작 + +## 📖 사용법 + +### 1. C# 코드 생성 + +1. StarUML에서 UML 클래스 다이어그램 작성 +2. 메뉴에서 `Tools` > `C#` > `Generate Code...` 선택 +3. 코드를 생성할 기본 모델(패키지) 선택 +4. 생성된 파일을 저장할 폴더 선택 +5. 코드 생성 완료 + +### 2. 설정 변경 + +1. 메뉴에서 `Tools` > `C#` > `Configure...` 선택 +2. 원하는 설정 변경: + - **CsharpDoc**: XML 문서 주석 생성 여부 + - **Use Tab**: 들여쓰기에 탭 사용 여부 + - **Indent Spaces**: 스페이스 들여쓰기 크기 (기본값: 4) + +## ⚙️ 설정 + +### 코드 생성 옵션 + +| 설정 | 설명 | 기본값 | +|------|------|--------| +| CsharpDoc | XML 문서 주석 생성 | true | +| Use Tab | 탭을 사용한 들여쓰기 | false | +| Indent Spaces | 스페이스 들여쓰기 크기 | 4 | + +## 🎯 지원하는 UML 요소 + +### 클래스 (Class) +- 속성 (Attributes) +- 메서드 (Operations) +- 가시성 (Visibility): public, private, protected, internal +- 정적 멤버 (Static members) +- 추상 클래스 (Abstract classes) + +### 인터페이스 (Interface) +- 메서드 시그니처 +- 속성 정의 + +### 열거형 (Enumeration) +- 열거 값들 +- 사용자 정의 값 + +### 관계 (Relationships) +- 상속 (Generalization) +- 구현 (Realization) +- 연관 (Association) +- 집합 (Aggregation) +- 합성 (Composition) + +## 💻 생성되는 C# 코드 예시 + +### UML 클래스에서 생성되는 C# 코드 + +**UML 클래스:** +``` +Person +- name: string +- age: int ++ getName(): string ++ setName(name: string): void +``` + +**생성되는 C# 코드:** +```csharp +/// +/// Person 클래스 +/// +public class Person +{ + /// + /// 이름 + /// + private string name; + + /// + /// 나이 + /// + private int age; + + /// + /// 이름을 반환합니다. + /// + /// 이름 + public string getName() + { + // TODO: 구현 필요 + return null; + } + + /// + /// 이름을 설정합니다. + /// + /// 설정할 이름 + public void setName(string name) + { + // TODO: 구현 필요 + } +} +``` + +## 🏗️ 프로젝트 구조 + +``` +├── main.js # 메인 진입점, 명령어 등록 +├── CsharpCodeGenerator.js # C# 코드 생성 로직 +├── CsharpPreferences.js # 사용자 설정 관리 +├── CodeGenUtils.js # 코드 생성 유틸리티 +├── package.json # 확장 프로그램 메타데이터 +└── README.md # 프로젝트 문서 +``` + +### 주요 모듈 설명 + +- **main.js**: StarUML 확장의 진입점으로, 메뉴 등록 및 명령어 핸들러 정의 +- **CsharpCodeGenerator.js**: UML 모델을 분석하여 C# 코드를 생성하는 핵심 로직 +- **CsharpPreferences.js**: 사용자 설정 관리 및 기본값 정의 +- **CodeGenUtils.js**: 코드 작성을 위한 유틸리티 클래스 (CodeWriter 등) + +## 🔧 개발 및 기여 + +### 개발 환경 설정 + +1. 저장소 클론 +```bash +git clone https://github.com/dongjoon1251/CSharp.git +``` + +2. StarUML 확장 폴더에 심볼릭 링크 생성 +3. StarUML에서 `Debug` > `Reload Extensions` 실행 + +### 코드 스타일 + +- JavaScript ES5 문법 사용 +- AMD 모듈 패턴 준수 +- JSLint 규칙 준수 + +## 🐛 알려진 이슈 + +- 역공학 기능은 현재 개발 중입니다 +- 복잡한 제네릭 타입 지원이 제한적입니다 +- 일부 C# 고급 기능은 지원되지 않을 수 있습니다 + +## 📞 지원 및 문의 + +- **이슈 리포트**: [GitHub Issues](https://github.com/dongjoon1251/CSharp/issues) +- **이메일**: joon1251@gmail.com + +## 👨‍💻 개발자 정보 + +- **개발자**: Dongjoon Lee +- **이메일**: joon1251@gmail.com +- **GitHub**: [@dongjoon1251](https://github.com/dongjoon1251) + +## 📄 라이선스 + +이 프로젝트는 MIT 라이선스 하에 배포됩니다. 자세한 내용은 [LICENSE](LICENSE) 파일을 참조하세요. + +--- + +## 🔄 버전 히스토리 + +### v0.1.0 +- 초기 릴리스 +- 기본 C# 코드 생성 기능 +- CsharpDoc 주석 생성 +- 사용자 설정 지원 + +--- + +**StarUML 2와 함께 더 효율적인 C# 개발을 경험해보세요!** 🚀 -C# extension for StarUML 2