summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjmusset2009-03-05 11:50:36 (EST)
committerjmusset2009-03-05 11:50:36 (EST)
commite7cb8983288502282ca430d098af937b78c5b42d (patch)
tree4322721b38b899035a52ebf480a0f1110eaacb35
parentee6e79b6449e616027c407ba2e21a9c8218a89e4 (diff)
downloadorg.eclipse.acceleo-e7cb8983288502282ca430d098af937b78c5b42d.zip
org.eclipse.acceleo-e7cb8983288502282ca430d098af937b78c5b42d.tar.gz
org.eclipse.acceleo-e7cb8983288502282ca430d098af937b78c5b42d.tar.bz2
Project renaming from MTL to Acceleo
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/.checkstyle12
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/.classpath8
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/.jetproperties4
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/.project40
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/.settings/org.eclipse.jdt.core.prefs7
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/META-INF/MANIFEST.MF45
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/about.html57
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/build.properties21
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/AcceleoEditor.gifbin0 -> 676 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/AcceleoLaunch.gifbin0 -> 676 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/AcceleoNature.gifbin0 -> 179 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/AcceleoNewProject.gifbin0 -> 487 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/AcceleoPerspective.gifbin0 -> 934 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/AcceleoRegion.gifbin0 -> 217 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/AcceleoResultView.gifbin0 -> 934 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/AcceleoWizard.gifbin0 -> 4203 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/debug/attribute.gifbin0 -> 329 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/debug/boolean.gifbin0 -> 365 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/debug/class.gifbin0 -> 228 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/debug/double.gifbin0 -> 361 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/debug/filteredBrkp.gifbin0 -> 594 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/debug/int.gifbin0 -> 367 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/debug/list.gifbin0 -> 355 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/debug/null.gifbin0 -> 361 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/debug/reference.gifbin0 -> 100 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/debug/string.gifbin0 -> 375 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/Block.gifbin0 -> 351 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/Comment.gifbin0 -> 324 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/FileBlock.gifbin0 -> 349 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/ForBlock.gifbin0 -> 330 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/IfBlock.gifbin0 -> 205 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/InitSection.gifbin0 -> 346 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/LetBlock.gifbin0 -> 139 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/Macro.gifbin0 -> 335 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/ModelExpression.gifbin0 -> 88 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/Module.gifbin0 -> 676 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/ModuleExtendsValue.gifbin0 -> 102 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/ModuleImportsValue.gifbin0 -> 153 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/ProtectedAreaBlock.gifbin0 -> 218 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/Query.gifbin0 -> 573 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/Template.gifbin0 -> 570 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/TemplateExpression.gifbin0 -> 214 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/TemplateOverridesValue.gifbin0 -> 152 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/Template_main.gifbin0 -> 599 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/TraceBlock.gifbin0 -> 225 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/TypedModel.gifbin0 -> 338 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/Variable.gifbin0 -> 78 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/EnumLiteral.gifbin0 -> 109 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/ForBlock.gifbin0 -> 330 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/IfBlock.gifbin0 -> 205 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/Keyword.gifbin0 -> 69 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/Macro.gifbin0 -> 335 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/Module.gifbin0 -> 676 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/Operation.gifbin0 -> 150 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/Pattern.gifbin0 -> 252 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/Property.gifbin0 -> 123 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/Query.gifbin0 -> 573 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/Template.gifbin0 -> 570 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/Type.gifbin0 -> 206 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/URI.gifbin0 -> 180 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/Variable.gifbin0 -> 78 bytes
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/plugin.properties35
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/plugin.xml497
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/schema/example.exsd104
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/schema/launching.exsd116
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/builders/runner/CreateRunnableAntCallWriter.java44
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/builders/runner/CreateRunnableAntWriter.java67
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/builders/runner/CreateRunnableJavaWriter.java81
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleActivatorWriter.java34
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleBuildWriter.java25
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleClasspathWriter.java25
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleMANIFESTWriter.java47
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleProjectWriter.java31
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleSettingsWriter.java25
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleUIActivatorWriter.java34
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleUIBuildWriter.java25
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleUIClasspathWriter.java25
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleUIGenerateAllWriter.java94
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleUIMANIFESTWriter.java47
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleUIPluginXMLWriter.java49
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleUIPopupMenuActionWriter.java44
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleUIProjectWriter.java31
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleUISettingsWriter.java25
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/ide/ui/AcceleoUIActivator.java114
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/ide/ui/launching/strategy/AcceleoPluginLaunchingStrategy.java41
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/ide/ui/launching/strategy/IAcceleoLaunchingStrategy.java53
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/ide/ui/natures/AcceleoNature.java96
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/ide/ui/resources/AcceleoProject.java519
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/ide/ui/wizards/newfile/example/AcceleoCopyExampleContentStrategy.java124
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/ide/ui/wizards/newfile/example/IAcceleoExampleStrategy.java73
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/AcceleoUIMessages.java81
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/acceleouimessages.properties139
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/builders/AcceleoBuilder.java339
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/builders/AcceleoCompileOperation.java232
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/builders/AcceleoMarker.java25
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/builders/runner/CreateRunnableAcceleoContent.java150
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/builders/runner/CreateRunnableAcceleoOperation.java350
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/actions/AbstractBreakpointRulerAction.java195
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/actions/BreakpointSelectModelRulerAction.java88
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/actions/RulerSelectModelActionDelegate.java35
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/core/AcceleoDebugger.java678
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/core/ITemplateDebugger.java134
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/core/ITemplateDebuggerListener.java50
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/core/StackInfo.java149
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AbstractDebugElement.java161
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoBreakpointAdapterFactory.java58
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoDebugTarget.java474
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoLineBreakpoint.java140
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoLineBreakpointAdapter.java186
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoModelPresentation.java202
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoProcess.java136
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoRunToLineAdapter.java80
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoRunToLineBreakpoint.java81
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoStackFrame.java327
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoThread.java285
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoValue.java327
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoVariable.java208
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoCompletionChoice.java123
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoCompletionProcessor.java1243
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoConfiguration.java212
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoDocumentProvider.java119
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoEditor.java513
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoEditorActionContributor.java55
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoElementHyperlinkDetector.java184
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoHover.java139
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoOutlinePage.java147
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoOutlinePageContentProvider.java70
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoOutlinePageItemProvider.java259
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoOutlinePageItemProviderAdapterFactory.java68
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoOutlinePageLabelProvider.java43
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoPairMatcher.java79
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoSourceContent.java942
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoTemplateReconcilingStrategy.java323
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/ColorManager.java59
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/actions/CommentAction.java135
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/actions/OpenDeclarationAction.java149
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/actions/references/ReferenceEntry.java168
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/actions/references/ReferenceLabelProvider.java87
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/actions/references/ReferenceSorter.java34
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/actions/references/ReferencesSearchAction.java74
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/actions/references/ReferencesSearchQuery.java308
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/actions/references/ReferencesSearchResult.java152
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/actions/references/ReferencesSearchViewPage.java147
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/actions/references/ReferencesTreeContentProvider.java312
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/rules/FirstVariableRule.java245
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/rules/ISequenceRule.java33
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/rules/KeywordRule.java171
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/rules/SequenceBlockRule.java237
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/rules/SequenceRule.java168
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/scanner/AbstractAcceleoScanner.java29
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/scanner/AcceleoBehavioralFeatureScanner.java87
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/scanner/AcceleoBlockScanner.java190
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/scanner/AcceleoCommentScanner.java51
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/scanner/AcceleoDefaultScanner.java49
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/scanner/AcceleoForScanner.java41
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/scanner/AcceleoIfScanner.java41
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/scanner/AcceleoLetScanner.java41
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/scanner/AcceleoPartitionScanner.java244
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/scanner/AcceleoProtectedAreaScanner.java57
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/scanner/AcceleoWhitespaceDetector.java31
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/scanner/IAcceleoColorConstants.java77
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/utils/OpenDeclarationUtils.java411
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/launching/AcceleoApplicationLaunchShortcut.java246
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/launching/AcceleoApplicationTabGroup.java54
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/launching/AcceleoJavaArgumentsTab.java93
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/launching/AcceleoLaunchDelegate.java306
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/launching/AcceleoLaunchDelegateStandalone.java95
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/launching/AcceleoLaunchOperation.java224
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/launching/AcceleoMainMethodSearchEngine.java223
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/launching/AcceleoMainTab.java638
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/launching/AcceleoSourceLookupDirector.java56
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/launching/AcceleoSourceLookupParticipant.java69
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/launching/AcceleoSourcePathComputer.java47
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/launching/IAcceleoLaunchConfigurationConstants.java47
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/launching/strategy/AcceleoJavaLaunchingStrategy.java38
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/natures/AcceleoToggleNatureAction.java160
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/perspectives/AcceleoPerspectiveFactory.java93
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/popupMenus/AcceleoNewProjectUIWizardAction.java91
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/views/result/AcceleoResultContent.java152
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/views/result/AcceleoResultFilesFilter.java78
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/views/result/AcceleoResultView.java350
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/views/result/TraceabilityContainer.java44
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/views/result/TraceabilityElement.java44
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/views/result/TraceabilityModel.java86
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/views/result/TraceabilityRegion.java120
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/views/result/TraceabilityTargetFile.java69
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/wizards/newfile/AbstractAcceleoNewTemplatesMasterComposite.java216
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/wizards/newfile/AcceleoNewTemplatesDetailsComposite.java997
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/wizards/newfile/AcceleoNewTemplatesGlobalController.java279
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/wizards/newfile/AcceleoNewTemplatesWizard.java264
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/wizards/newfile/AcceleoNewTemplatesWizardController.java254
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/wizards/newfile/AcceleoNewTemplatesWizardPage.java147
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/wizards/newfile/CreateTemplateData.java366
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/wizards/newfile/example/AbstractM2TContentStrategy.java315
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/wizards/newfile/example/AcceleoExampleStrategyUtils.java102
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/wizards/newfile/example/MTContentStrategy.java258
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/wizards/newfile/example/XpandContentStrategy.java161
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/AcceleoNewProjectUIWizard.java533
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/AcceleoNewProjectWizard.java312
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/AcceleoNewUIConfigurationPage.java279
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleData.java180
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleUIData.java259
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/templates/createModuleActivatorWriter.jet74
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/templates/createModuleBuildWriter.jet10
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/templates/createModuleClasspathWriter.jet12
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/templates/createModuleMANIFESTWriter.jet26
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/templates/createModuleProjectWriter.jet42
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/templates/createModuleSettingsWriter.jet11
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/templates/createModuleUIActivatorWriter.jet76
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/templates/createModuleUIBuildWriter.jet12
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/templates/createModuleUIClasspathWriter.jet12
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/templates/createModuleUIGenerateAllWriter.jet161
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/templates/createModuleUIMANIFESTWriter.jet28
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/templates/createModuleUIPluginXMLWriter.jet30
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/templates/createModuleUIPopupMenuActionWriter.jet123
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/templates/createModuleUIProjectWriter.jet36
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/templates/createModuleUISettingsWriter.jet11
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/templates/createRunnableAntCallWriter.jet24
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/templates/createRunnableAntWriter.jet31
-rw-r--r--plugins/org.eclipse.acceleo.ide.ui/templates/createRunnableJavaWriter.jet300
220 files changed, 25740 insertions, 0 deletions
diff --git a/plugins/org.eclipse.acceleo.ide.ui/.checkstyle b/plugins/org.eclipse.acceleo.ide.ui/.checkstyle
new file mode 100644
index 0000000..6703757
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/.checkstyle
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<fileset-config file-format-version="1.2.0" simple-config="true">
+ <local-check-config name="Acceleo" location="/org.eclipse.acceleo-feature/codestyle/AcceleoCheckstyleConfiguration.xml" type="project" description="">
+ <additional-data name="protect-config-file" value="false"/>
+ </local-check-config>
+ <fileset name="tous" enabled="true" check-config-name="Acceleo" local="true">
+ <file-match-pattern match-pattern="." include-pattern="true"/>
+ </fileset>
+ <filter name="FilesFromPackage" enabled="true">
+ <filter-data value="src-gen"/>
+ </filter>
+</fileset-config>
diff --git a/plugins/org.eclipse.acceleo.ide.ui/.classpath b/plugins/org.eclipse.acceleo.ide.ui/.classpath
new file mode 100644
index 0000000..59cf397
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="src-gen"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/plugins/org.eclipse.acceleo.ide.ui/.jetproperties b/plugins/org.eclipse.acceleo.ide.ui/.jetproperties
new file mode 100644
index 0000000..7be3f57
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/.jetproperties
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<jet-settings>
+ <template-container>templates</template-container> <source-container>src-gen</source-container>
+</jet-settings>
diff --git a/plugins/org.eclipse.acceleo.ide.ui/.project b/plugins/org.eclipse.acceleo.ide.ui/.project
new file mode 100644
index 0000000..55d8887
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/.project
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.acceleo.ide.ui</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.emf.codegen.JETBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.atlassw.tools.eclipse.checkstyle.CheckstyleBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.emf.codegen.jet.IJETNature</nature>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>com.atlassw.tools.eclipse.checkstyle.CheckstyleNature</nature>
+ </natures>
+</projectDescription>
diff --git a/plugins/org.eclipse.acceleo.ide.ui/.settings/org.eclipse.jdt.core.prefs b/plugins/org.eclipse.acceleo.ide.ui/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..5d1c0fc
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+#Fri May 23 13:23:11 CEST 2008
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.5
diff --git a/plugins/org.eclipse.acceleo.ide.ui/META-INF/MANIFEST.MF b/plugins/org.eclipse.acceleo.ide.ui/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..e81a539
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/META-INF/MANIFEST.MF
@@ -0,0 +1,45 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %pluginName
+Bundle-SymbolicName: org.eclipse.acceleo.ide.ui; singleton:=true
+Bundle-Version: 0.8.0.qualifier
+Bundle-Activator: org.eclipse.acceleo.ide.ui.AcceleoUIActivator
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.eclipse.jface.text,
+ org.eclipse.ui.editors,
+ org.eclipse.core.resources,
+ org.eclipse.jdt.core,
+ org.eclipse.emf.ecore.xmi,
+ org.eclipse.acceleo.parser,
+ org.eclipse.acceleo.common,
+ org.eclipse.pde.core,
+ org.eclipse.emf.edit.ui,
+ org.eclipse.emf.ecore.edit,
+ org.eclipse.jdt.ui,
+ org.eclipse.ocl.ecore,
+ org.eclipse.acceleo.model,
+ org.eclipse.ui.ide,
+ org.eclipse.debug.ui,
+ org.eclipse.ui.console,
+ org.eclipse.search,
+ org.eclipse.acceleo.engine,
+ org.eclipse.emf.codegen,
+ org.eclipse.emf.ecore.editor,
+ org.eclipse.jdt.launching,
+ org.eclipse.jdt.debug.ui,
+ org.eclipse.jdt.debug,
+ org.eclipse.search,
+ org.eclipse.ui.workbench.texteditor
+Eclipse-LazyStart: true
+Bundle-ActivationPolicy: lazy
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
+Export-Package: org.eclipse.acceleo.ide.ui,
+ org.eclipse.acceleo.ide.ui.launching.strategy,
+ org.eclipse.acceleo.ide.ui.natures,
+ org.eclipse.acceleo.ide.ui.resources,
+ org.eclipse.acceleo.ide.ui.wizards.newfile.example,
+ org.eclipse.acceleo.internal.ide.ui.editors.template;x-friends:="org.eclipse.acceleo.ide.ui.tests",
+ org.eclipse.acceleo.internal.ide.ui.editors.template.rules;x-friends:="org.eclipse.acceleo.ide.ui.tests"
diff --git a/plugins/org.eclipse.acceleo.ide.ui/about.html b/plugins/org.eclipse.acceleo.ide.ui/about.html
new file mode 100644
index 0000000..7e1117e
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/about.html
@@ -0,0 +1,57 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"><head>
+
+
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>About</title>
+</head><body lang="EN-US">
+<h2>About This Content</h2>
+
+<em>July 25, 2008</em></p>
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available
+at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, "Program" will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
+being redistributed by another party ("Redistributor") and different terms and conditions may
+apply to your use of any object code in the Content. Check the Redistributor's license that was
+provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
+
+
+ <h3>Third Party Content</h3>
+ <p>The Content includes items that have been sourced from third parties as set out below. If you
+ did not receive this Content directly from the Eclipse Foundation, the following is provided
+ for informational purposes only, and you should look to the Redistributor's license for
+ terms and conditions of use.</p>
+ <p><em>
+ <br><br>
+ <strong>OMG MOF 2.0 Specification (06-01-01)</strong> <br>
+ <ul>
+ <li><a href="http://www.omg.org/technology/documents/formal/mof.htm">MOF 2.0 main page</a></li>
+ <li><a href="http://www.omg.org/docs/formal/06-01-01.pdf">MOF 2.0 specification</a></li>
+ <li><a href="http://www.omg.org/">OMG site</a></li>
+ </ul>
+ <br>
+ <strong>OMG OCL 2.0 specification (06-05-01)</strong> <br>
+ <ul>
+ <li><a href="http://www.omg.org/technology/documents/formal/ocl.htm">OCL 2.0 main page</a></li>
+ <li><a href="http://www.omg.org/docs/formal/06-05-01.pdf">OCL 2.0 specification</a></li>
+ <li><a href="http://www.omg.org/">OMG site</a></li>
+ </ul>
+ <br>
+ <strong>OMG MTL 1.0 specification (08-01-16)</strong> <br>
+ <ul>
+ <li><a href="http://www.omg.org/spec/MOFM2T/1.0/">MTL 1.0 main page</a></li>
+ <li><a href="http://www.omg.org/spec/MOFM2T/1.0/PDF">MTL 1.0 specification</a></li>
+ <li><a href="http://www.omg.org/">OMG site</a></li>
+ </ul>
+ <br>
+ </em></p>
+ <p>A detailed list of fixes and clarifications with respect to those specifications may be found in the plug-in directly realizing them.</p>
+</body></html> \ No newline at end of file
diff --git a/plugins/org.eclipse.acceleo.ide.ui/build.properties b/plugins/org.eclipse.acceleo.ide.ui/build.properties
new file mode 100644
index 0000000..f09cefc
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/build.properties
@@ -0,0 +1,21 @@
+################################################################################
+# Copyright (c) 2008, 2009 Obeo.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# Obeo - initial API and implementation
+################################################################################
+source.. = src/,\
+ src-gen/
+output.. = bin/
+bin.includes = plugin.xml,\
+ META-INF/,\
+ .,\
+ icons/,\
+ schema/,\
+ about.html,\
+ plugin.properties
+Bundle-ClassPath: .
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/AcceleoEditor.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/AcceleoEditor.gif
new file mode 100644
index 0000000..d8a3137
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/AcceleoEditor.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/AcceleoLaunch.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/AcceleoLaunch.gif
new file mode 100644
index 0000000..d8a3137
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/AcceleoLaunch.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/AcceleoNature.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/AcceleoNature.gif
new file mode 100644
index 0000000..47894a6
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/AcceleoNature.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/AcceleoNewProject.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/AcceleoNewProject.gif
new file mode 100644
index 0000000..a70e9fa
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/AcceleoNewProject.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/AcceleoPerspective.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/AcceleoPerspective.gif
new file mode 100644
index 0000000..82e8a5a
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/AcceleoPerspective.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/AcceleoRegion.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/AcceleoRegion.gif
new file mode 100644
index 0000000..c4b831d
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/AcceleoRegion.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/AcceleoResultView.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/AcceleoResultView.gif
new file mode 100644
index 0000000..82e8a5a
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/AcceleoResultView.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/AcceleoWizard.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/AcceleoWizard.gif
new file mode 100644
index 0000000..008b8b6
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/AcceleoWizard.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/debug/attribute.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/debug/attribute.gif
new file mode 100644
index 0000000..99b7fa6
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/debug/attribute.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/debug/boolean.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/debug/boolean.gif
new file mode 100644
index 0000000..656797f
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/debug/boolean.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/debug/class.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/debug/class.gif
new file mode 100644
index 0000000..7c33c76
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/debug/class.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/debug/double.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/debug/double.gif
new file mode 100644
index 0000000..f1f0195
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/debug/double.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/debug/filteredBrkp.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/debug/filteredBrkp.gif
new file mode 100644
index 0000000..fa74e39
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/debug/filteredBrkp.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/debug/int.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/debug/int.gif
new file mode 100644
index 0000000..3bd99b3
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/debug/int.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/debug/list.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/debug/list.gif
new file mode 100644
index 0000000..e0347d8
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/debug/list.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/debug/null.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/debug/null.gif
new file mode 100644
index 0000000..d28f9cc
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/debug/null.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/debug/reference.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/debug/reference.gif
new file mode 100644
index 0000000..3b687d2
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/debug/reference.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/debug/string.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/debug/string.gif
new file mode 100644
index 0000000..ef367ef
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/debug/string.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/Block.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/Block.gif
new file mode 100644
index 0000000..6451412
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/Block.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/Comment.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/Comment.gif
new file mode 100644
index 0000000..c495731
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/Comment.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/FileBlock.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/FileBlock.gif
new file mode 100644
index 0000000..f9e56ee
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/FileBlock.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/ForBlock.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/ForBlock.gif
new file mode 100644
index 0000000..ae55cda
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/ForBlock.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/IfBlock.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/IfBlock.gif
new file mode 100644
index 0000000..c941e9b
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/IfBlock.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/InitSection.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/InitSection.gif
new file mode 100644
index 0000000..0667887
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/InitSection.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/LetBlock.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/LetBlock.gif
new file mode 100644
index 0000000..ac711ac
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/LetBlock.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/Macro.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/Macro.gif
new file mode 100644
index 0000000..a22358e
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/Macro.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/ModelExpression.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/ModelExpression.gif
new file mode 100644
index 0000000..4c5d117
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/ModelExpression.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/Module.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/Module.gif
new file mode 100644
index 0000000..d8a3137
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/Module.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/ModuleExtendsValue.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/ModuleExtendsValue.gif
new file mode 100644
index 0000000..d6e7b15
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/ModuleExtendsValue.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/ModuleImportsValue.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/ModuleImportsValue.gif
new file mode 100644
index 0000000..dd39064
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/ModuleImportsValue.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/ProtectedAreaBlock.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/ProtectedAreaBlock.gif
new file mode 100644
index 0000000..e74cb96
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/ProtectedAreaBlock.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/Query.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/Query.gif
new file mode 100644
index 0000000..482a4d5
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/Query.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/Template.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/Template.gif
new file mode 100644
index 0000000..bec9f0e
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/Template.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/TemplateExpression.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/TemplateExpression.gif
new file mode 100644
index 0000000..48f39c4
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/TemplateExpression.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/TemplateOverridesValue.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/TemplateOverridesValue.gif
new file mode 100644
index 0000000..fc9ec31
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/TemplateOverridesValue.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/Template_main.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/Template_main.gif
new file mode 100644
index 0000000..5306e27
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/Template_main.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/TraceBlock.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/TraceBlock.gif
new file mode 100644
index 0000000..a024c49
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/TraceBlock.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/TypedModel.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/TypedModel.gif
new file mode 100644
index 0000000..86ab581
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/TypedModel.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/Variable.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/Variable.gif
new file mode 100644
index 0000000..b156d84
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/Variable.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/EnumLiteral.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/EnumLiteral.gif
new file mode 100644
index 0000000..7bb44f5
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/EnumLiteral.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/ForBlock.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/ForBlock.gif
new file mode 100644
index 0000000..ae55cda
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/ForBlock.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/IfBlock.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/IfBlock.gif
new file mode 100644
index 0000000..c941e9b
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/IfBlock.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/Keyword.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/Keyword.gif
new file mode 100644
index 0000000..1be9094
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/Keyword.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/Macro.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/Macro.gif
new file mode 100644
index 0000000..a22358e
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/Macro.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/Module.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/Module.gif
new file mode 100644
index 0000000..d8a3137
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/Module.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/Operation.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/Operation.gif
new file mode 100644
index 0000000..5818a30
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/Operation.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/Pattern.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/Pattern.gif
new file mode 100644
index 0000000..3091c61
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/Pattern.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/Property.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/Property.gif
new file mode 100644
index 0000000..bc9944a
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/Property.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/Query.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/Query.gif
new file mode 100644
index 0000000..482a4d5
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/Query.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/Template.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/Template.gif
new file mode 100644
index 0000000..bec9f0e
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/Template.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/Type.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/Type.gif
new file mode 100644
index 0000000..2b8da63
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/Type.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/URI.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/URI.gif
new file mode 100644
index 0000000..b26c71d
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/URI.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/Variable.gif b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/Variable.gif
new file mode 100644
index 0000000..b156d84
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/icons/template-editor/completion/Variable.gif
Binary files differ
diff --git a/plugins/org.eclipse.acceleo.ide.ui/plugin.properties b/plugins/org.eclipse.acceleo.ide.ui/plugin.properties
new file mode 100644
index 0000000..8627c6c
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/plugin.properties
@@ -0,0 +1,35 @@
+#################################################################################
+# Copyright (c) 2008, 2009 Obeo.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# Obeo - initial API and implementation
+#################################################################################
+# NLS_MESSAGEFORMAT_VAR
+acceleo=Model to Text Transformation
+
+pluginName = Acceleo Eclipse User Interface
+providerName = Eclipse Modeling Project
+
+acceleoSourceLocatorName = Acceleo Source Lookup Directory
+acceleoLaunchConfigurationGroupName = Create a configuration to launch an Acceleo application.
+acceleoLaunchConfigurationName=Acceleo Application
+acceleoShortcutLaunchLabel=Acceleo Application
+
+breakpointName = Acceleo Line Breakpoints
+breakpointMarkerName = Acceleo Line Breakpoint Marker
+contextName = Debugging Acceleo
+contextDescription = Debugging Acceleo
+
+AcceleoModuleDescription = Create a new Acceleo generation module.
+AcceleoUIModuleDescription = Create a new UI module for Acceleo. This will add a plugin with all necessary code for an action "Acceleo > Launch" on candidate models.
+AcceleoTemplateDescription = Create a new Acceleo generation template.
+
+# Search References
+acceleoEditorActionReferencesSearch.Label = Search References
+acceleoEditorActionReferencesSearch.Tooltip = Search the element references
+acceleoEditorCommandsReferencesSearch.Description = Search the element references
+acceleoEditorCommandsReferencesSearch.Name = Search references \ No newline at end of file
diff --git a/plugins/org.eclipse.acceleo.ide.ui/plugin.xml b/plugins/org.eclipse.acceleo.ide.ui/plugin.xml
new file mode 100644
index 0000000..f416a90
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/plugin.xml
@@ -0,0 +1,497 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.2"?>
+
+<!--
+Copyright (c) 2008, 2009 Obeo.
+All rights reserved. This program and the accompanying materials
+are made available under the terms of the Eclipse Public License v1.0
+which accompanies this distribution, and is available at
+http://www.eclipse.org/legal/epl-v10.html
+
+Contributors:
+ Obeo - initial API and implementation
+-->
+
+<plugin>
+
+ <extension-point id="example" name="org.eclipse.acceleo.ide.ui.example" schema="schema/example.exsd"/>
+
+ <extension point="org.eclipse.acceleo.ide.ui.example">
+ <strategy
+ class="org.eclipse.acceleo.ide.ui.wizards.newfile.example.AcceleoCopyExampleContentStrategy"/>
+ </extension>
+
+ <extension point="org.eclipse.acceleo.ide.ui.example">
+ <strategy
+ class="org.eclipse.acceleo.internal.ide.ui.wizards.newfile.example.MTContentStrategy"/>
+ </extension>
+
+ <extension point="org.eclipse.acceleo.ide.ui.example">
+ <strategy
+ class="org.eclipse.acceleo.internal.ide.ui.wizards.newfile.example.XpandContentStrategy"/>
+ </extension>
+
+ <extension-point id="launching" name="org.eclipse.acceleo.ide.ui.launching" schema="schema/launching.exsd"/>
+
+ <!-- The description attribute mustn't be modified -->
+ <extension point="org.eclipse.acceleo.ide.ui.launching">
+ <strategy
+ description="Acceleo Plug-in Application"
+ class="org.eclipse.acceleo.ide.ui.launching.strategy.AcceleoPluginLaunchingStrategy"/>
+ </extension>
+ <extension point="org.eclipse.acceleo.ide.ui.launching">
+ <strategy
+ description="Java Application"
+ class="org.eclipse.acceleo.internal.ide.ui.launching.strategy.AcceleoJavaLaunchingStrategy"/>
+ </extension>
+
+ <extension point="org.eclipse.core.resources.builders" id="acceleoBuilder" name="Acceleo Builder">
+ <builder hasNature="true">
+ <run class="org.eclipse.acceleo.internal.ide.ui.builders.AcceleoBuilder" />
+ </builder>
+ </extension>
+
+ <extension point="org.eclipse.core.resources.natures" id="acceleoNature" name="Acceleo Nature">
+ <runtime>
+ <run class="org.eclipse.acceleo.ide.ui.natures.AcceleoNature" />
+ </runtime>
+ <builder id="org.eclipse.acceleo.ide.ui.acceleoBuilder"/>
+ </extension>
+
+ <extension id="problem" point="org.eclipse.core.resources.markers" name="Acceleo Problem">
+ <super type="org.eclipse.core.resources.problemmarker" />
+ <persistent value="true" />
+ </extension>
+
+ <extension point="org.eclipse.ui.ide.projectNatureImages">
+ <image
+ id="org.eclipse.acceleo.ide.ui.acceleoNatureImage"
+ natureId="org.eclipse.acceleo.ide.ui.acceleoNature"
+ icon="icons/AcceleoNature.gif">
+ </image>
+ </extension>
+
+ <extension point="org.eclipse.ui.popupMenus">
+ <objectContribution
+ adaptable="true"
+ objectClass="org.eclipse.core.resources.IProject"
+ nameFilter="*"
+ id="org.eclipse.acceleo.ide.ui.popupMenus.contribution.IProject">
+ <menu id="org.eclipse.acceleo.ide.ui.menu" label="Acceleo" path="additionsAcceleo">
+ <groupMarker name="acceleo"/>
+ </menu>
+ <action
+ class="org.eclipse.acceleo.internal.ide.ui.natures.AcceleoToggleNatureAction"
+ enablesFor="+"
+ id="org.eclipse.acceleo.ide.ui.natures.addRemoveNatureAction"
+ icon = "icons/AcceleoNature.gif"
+ label="Remove Acceleo Nature"
+ menubarPath="org.eclipse.acceleo.ide.ui.menu/acceleo"/>
+ <filter
+ name="nature"
+ value="org.eclipse.acceleo.ide.ui.acceleoNature"/>
+ <action
+ class="org.eclipse.acceleo.internal.ide.ui.popupMenus.AcceleoNewProjectUIWizardAction"
+ enablesFor="1"
+ id="org.eclipse.acceleo.ide.ui.popupMenus.AcceleoNewProjectUIWizardAction"
+ icon = "icons/AcceleoNewProject.gif"
+ label="Create Acceleo Module UI Project"
+ menubarPath="org.eclipse.acceleo.ide.ui.menu/acceleo"/>
+ <filter
+ name="nature"
+ value="org.eclipse.acceleo.ide.ui.acceleoNature"/>
+ </objectContribution>
+ </extension>
+
+ <extension
+ point="org.eclipse.ui.editors">
+ <editor
+ class="org.eclipse.acceleo.internal.ide.ui.editors.template.AcceleoEditor"
+ icon="icons/AcceleoEditor.gif"
+ contributorClass="org.eclipse.acceleo.internal.ide.ui.editors.template.AcceleoEditorActionContributor"
+ name="Acceleo Template Editor"
+ extensions="mtl"
+ id="org.eclipse.acceleo.ide.ui.editors.template.AcceleoEditor"/>
+ </extension>
+
+ <extension
+ point="org.eclipse.ui.actionSets">
+ <actionSet
+ label="Acceleo Editor Actions"
+ description="Acceleo Editor Actions"
+ visible="false"
+ id="org.eclipse.acceleo.ide.ui.editors.template.actionSet">
+ <action
+ allowLabelUpdate="true"
+ class="org.eclipse.acceleo.internal.ide.ui.editors.template.actions.OpenDeclarationAction"
+ definitionId="org.eclipse.acceleo.ide.ui.open.declaration"
+ enablesFor="*"
+ id="org.eclipse.acceleo.ide.ui.editors.template.actions.open.declaration"
+ label="Open Declaration"
+ retarget="false"
+ tooltip="Open Declaration">
+ </action>
+ <action
+ allowLabelUpdate="true"
+ class="org.eclipse.acceleo.internal.ide.ui.editors.template.actions.references.ReferencesSearchAction"
+ definitionId="org.eclipse.acceleo.ide.ui.search.references"
+ enablesFor="*"
+ id="org.eclipse.acceleo.ide.ui.editors.template.actions.search.references"
+ label="%acceleoEditorActionReferencesSearch.Label"
+ retarget="false"
+ tooltip="%acceleoEditorActionReferencesSearch.Tooltip">
+ </action>
+ <action
+ allowLabelUpdate="true"
+ class="org.eclipse.acceleo.internal.ide.ui.editors.template.actions.CommentAction"
+ definitionId="org.eclipse.acceleo.ide.ui.comment"
+ enablesFor="*"
+ id="org.eclipse.acceleo.ide.ui.editors.template.actions.comment"
+ label="Comment"
+ retarget="false"
+ tooltip="Comment">
+ </action>
+ </actionSet>
+ </extension>
+
+ <extension
+ point="org.eclipse.ui.commands">
+ <command
+ categoryId="org.eclipse.ui.category.navigate"
+ description="Open Declaration"
+ id="org.eclipse.acceleo.ide.ui.open.declaration"
+ name="Open Declaration">
+ </command>
+ <command
+ categoryId="org.eclipse.ui.category.navigate"
+ description="%acceleoEditorCommandsReferencesSearch.Description"
+ id="org.eclipse.acceleo.ide.ui.search.references"
+ name="%acceleoEditorCommandsReferencesSearch.Name">
+ </command>
+ <command
+ categoryId="org.eclipse.ui.category.navigate"
+ description="Comment"
+ id="org.eclipse.acceleo.ide.ui.comment"
+ name="Comment">
+ </command>
+ </extension>
+
+ <extension
+ point="org.eclipse.ui.contexts">
+ <context
+ name="Acceleo Editor"
+ description="Acceleo editing template context"
+ parentId="org.eclipse.ui.textEditorScope"
+ id="org.eclipse.acceleo.ide.ui.editors.template.editor">
+ </context>
+ </extension>
+ <extension
+ point="org.eclipse.ui.bindings">
+ <key
+ commandId="org.eclipse.acceleo.ide.ui.open.declaration"
+ contextId="org.eclipse.acceleo.ide.ui.editors.template.editor"
+ schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
+ sequence="F3"/>
+ <key
+ commandId="org.eclipse.acceleo.ide.ui.search.references"
+ contextId="org.eclipse.acceleo.ide.ui.editors.template.editor"
+ schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
+ sequence="M1+M2+G"/>
+ <key
+ commandId="org.eclipse.acceleo.ide.ui.comment"
+ contextId="org.eclipse.acceleo.ide.ui.editors.template.editor"
+ schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
+ sequence="M1+M2+C"/>
+ <key
+ commandId="org.eclipse.acceleo.ide.ui.comment"
+ contextId="org.eclipse.acceleo.ide.ui.editors.template.editor"
+ schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
+ sequence="M1+/"/>
+ </extension>
+
+ <extension
+ point="org.eclipse.ui.perspectiveExtensions">
+ <perspectiveExtension targetID="org.eclipse.jdt.ui.JavaPerspective">
+ <actionSet
+ id="org.eclipse.acceleo.ide.ui.editors.template.actionSet">
+ </actionSet>
+ </perspectiveExtension>
+ <perspectiveExtension targetID="org.eclipse.debug.ui.DebugPerspective">
+ <actionSet
+ id="org.eclipse.acceleo.ide.ui.editors.template.actionSet">
+ </actionSet>
+ </perspectiveExtension>
+ <perspectiveExtension targetID="org.eclipse.acceleo.ide.ui.AcceleoPerspective">
+ <actionSet
+ id="org.eclipse.acceleo.ide.ui.editors.template.actionSet">
+ </actionSet>
+ <view
+ id="org.eclipse.acceleo.ide.ui.views.result.AcceleoResultView"
+ ratio="0.5"
+ relationship="right"
+ relative="org.eclipse.ui.views.TaskList">
+ </view>
+ </perspectiveExtension>
+ </extension>
+ <extension
+ point="org.eclipse.ui.newWizards">
+ <category
+ id="org.eclipse.acceleo.ide.ui"
+ name="%acceleo">
+ </category>
+ <wizard
+ category="org.eclipse.acceleo.ide.ui"
+ class="org.eclipse.acceleo.internal.ide.ui.wizards.newfile.AcceleoNewTemplatesWizard"
+ icon="icons/AcceleoEditor.gif"
+ id="org.eclipse.acceleo.ide.ui.wizards.newfile.AcceleoNewTemplatesWizard"
+ name="Acceleo Template"
+ finalPerspective="org.eclipse.acceleo.ide.ui.AcceleoPerspective">
+ <description>
+ %AcceleoTemplateDescription
+ </description>
+ </wizard>
+ <wizard
+ category="org.eclipse.acceleo.ide.ui"
+ class="org.eclipse.acceleo.internal.ide.ui.wizards.newproject.AcceleoNewProjectWizard"
+ icon="icons/AcceleoNewProject.gif"
+ id="org.eclipse.acceleo.ide.ui.wizards.newproject.AcceleoNewProjectWizard"
+ name="Acceleo Module Project"
+ finalPerspective="org.eclipse.acceleo.ide.ui.AcceleoPerspective"
+ project="true">
+ <description>
+ %AcceleoModuleDescription
+ </description>
+ </wizard>
+ <wizard
+ category="org.eclipse.acceleo.ide.ui"
+ class="org.eclipse.acceleo.internal.ide.ui.wizards.newproject.AcceleoNewProjectUIWizard"
+ icon="icons/AcceleoNewProject.gif"
+ id="org.eclipse.acceleo.ide.ui.wizards.newproject.AcceleoNewProjectUIWizard"
+ name="Acceleo Module UI Project"
+ finalPerspective="org.eclipse.acceleo.ide.ui.AcceleoPerspective"
+ project="true">
+ <description>
+ %AcceleoUIModuleDescription
+ </description>
+ </wizard>
+ </extension>
+
+ <extension point="org.eclipse.ui.perspectives">
+ <perspective
+ name="Acceleo"
+ icon="/icons/AcceleoPerspective.gif"
+ class="org.eclipse.acceleo.internal.ide.ui.perspectives.AcceleoPerspectiveFactory"
+ id="org.eclipse.acceleo.ide.ui.AcceleoPerspective">
+ </perspective>
+ </extension>
+
+ <extension point="org.eclipse.debug.core.launchConfigurationTypes">
+ <launchConfigurationType
+ sourceLocatorId="org.eclipse.acceleo.ide.ui.launching.AcceleoSourceLookupDirector"
+ name="%acceleoLaunchConfigurationName"
+ sourcePathComputerId="org.eclipse.acceleo.ide.ui.launching.AcceleoSourcePathComputer"
+ delegate="org.eclipse.acceleo.internal.ide.ui.launching.AcceleoLaunchDelegate"
+ modes="run, debug"
+ id="org.eclipse.acceleo.ide.ui.launching.launchConfigurationType">
+ </launchConfigurationType>
+ </extension>
+
+ <extension point="org.eclipse.debug.core.sourceLocators">
+ <sourceLocator
+ name="%acceleoSourceLocatorName"
+ class="org.eclipse.acceleo.internal.ide.ui.launching.AcceleoSourceLookupDirector"
+ id="org.eclipse.acceleo.ide.ui.launching.AcceleoSourceLookupDirector">
+ </sourceLocator>
+ </extension>
+
+ <extension point="org.eclipse.debug.core.sourcePathComputers">
+ <sourcePathComputer
+ class="org.eclipse.acceleo.internal.ide.ui.launching.AcceleoSourcePathComputer"
+ id="org.eclipse.acceleo.ide.ui.launching.AcceleoSourcePathComputer">
+ </sourcePathComputer>
+ </extension>
+
+ <extension point="org.eclipse.debug.ui.launchConfigurationTypeImages">
+ <launchConfigurationTypeImage
+ icon="icons/AcceleoLaunch.gif"
+ configTypeID="org.eclipse.acceleo.ide.ui.launching.launchConfigurationType"
+ id="org.eclipse.acceleo.ide.ui.launching.launchConfigurationTypeImage">
+ </launchConfigurationTypeImage>
+ </extension>
+
+ <extension point="org.eclipse.debug.ui.launchConfigurationTabGroups">
+ <launchConfigurationTabGroup
+ type="org.eclipse.acceleo.ide.ui.launching.launchConfigurationType"
+ description="%acceleoLaunchConfigurationGroupName"
+ class="org.eclipse.acceleo.internal.ide.ui.launching.AcceleoApplicationTabGroup"
+ id="org.eclipse.acceleo.ide.ui.launching.AcceleoApplicationTabGroup">
+ </launchConfigurationTabGroup>
+ </extension>
+
+ <extension
+ point="org.eclipse.debug.ui.launchShortcuts">
+ <shortcut
+ label="%acceleoShortcutLaunchLabel"
+ icon="icons/AcceleoLaunch.gif"
+ class="org.eclipse.acceleo.internal.ide.ui.launching.AcceleoApplicationLaunchShortcut"
+ modes="run, debug"
+ id="org.eclipse.acceleo.ide.ui.launching.AcceleoApplicationLaunchShortcut">
+ <contextualLaunch>
+ <enablement>
+ <with variable="selection">
+ <count value="1"/>
+ <iterate>
+ <or>
+ <test property="org.eclipse.debug.ui.matchesPattern" value="*.mtl"/>
+ <and>
+ <test property="org.eclipse.jdt.launching.isContainer"/>
+ <test property="org.eclipse.jdt.launching.hasProjectNature" args="org.eclipse.acceleo.ide.ui.acceleoNature"/>
+ </and>
+ <and>
+ <adapt type="org.eclipse.jdt.core.IJavaElement">
+ <test property="org.eclipse.jdt.core.isInJavaProject"/>
+ </adapt>
+ <or>
+ <test property="org.eclipse.jdt.launching.hasProjectNature" args="org.eclipse.acceleo.ide.ui.acceleoNature"/>
+ <test property="org.eclipse.jdt.launching.hasMain"/>
+ <test property="org.eclipse.jdt.launching.isContainer"/>
+ <test property="org.eclipse.jdt.launching.isPackageFragment"/>
+ <test property="org.eclipse.jdt.launching.isPackageFragmentRoot"/>
+ </or>
+ </and>
+ </or>
+ </iterate>
+ </with>
+ </enablement>
+ </contextualLaunch>
+ </shortcut>
+ </extension>
+
+ <extension
+ point="org.eclipse.debug.ui.debugModelPresentations">
+ <debugModelPresentation
+ class="org.eclipse.acceleo.internal.ide.ui.debug.model.AcceleoModelPresentation"
+ id="org.eclipse.acceleo.ide.ui.debug.model.AcceleoModelPresentation">
+ </debugModelPresentation>
+ </extension>
+
+ <extension
+ point="org.eclipse.debug.core.breakpoints">
+ <breakpoint
+ markerType="org.eclipse.acceleo.ide.ui.debug.markerType.lineBreakpoint"
+ class="org.eclipse.acceleo.internal.ide.ui.debug.model.AcceleoLineBreakpoint"
+ id="org.eclipse.acceleo.ide.ui.debug.model.AcceleoLineBreakpoint"
+ name="%breakpointName">
+ </breakpoint>
+ </extension>
+
+ <extension
+ id="org.eclipse.acceleo.ide.ui.debug.markerType.lineBreakpoint"
+ name="%breakpointMarkerName"
+ point="org.eclipse.core.resources.markers">
+ <super type="org.eclipse.debug.core.lineBreakpointMarker"/>
+ <persistent value="true"/>
+ <attribute name="astFragment"/>
+ </extension>
+
+ <extension
+ point="org.eclipse.core.runtime.adapters">
+ <factory
+ class="org.eclipse.acceleo.internal.ide.ui.debug.model.AcceleoBreakpointAdapterFactory"
+ adaptableType="org.eclipse.acceleo.internal.ide.ui.editors.template.AcceleoEditor">
+ <adapter type="org.eclipse.debug.ui.actions.IToggleBreakpointsTarget"/>
+ <adapter type="org.eclipse.debug.ui.actions.IRunToLineTarget"/>
+ </factory>
+ </extension>
+
+ <extension
+ point="org.eclipse.ui.editorActions">
+ <editorContribution
+ targetID="org.eclipse.acceleo.ide.ui.editors.template.AcceleoEditor"
+ id="acceleo.rulerActions">
+ <action
+ label="Toggle Acceleo Breakpoint"
+ class="org.eclipse.debug.ui.actions.RulerToggleBreakpointActionDelegate"
+ style="push"
+ actionID="RulerDoubleClick"
+ id="org.eclipse.acceleo.ide.ui.debug.actions.doubleClickBreakpointAction"/>
+ <action
+ label="Filter Acceleo Breakpoint"
+ class="org.eclipse.acceleo.internal.ide.ui.debug.actions.RulerSelectModelActionDelegate"
+ style="push"
+ actionID="RulerClick"
+ id="org.eclipse.acceleo.ide.ui.debug.actions.clickBreakpointAction"/>
+ </editorContribution>
+ </extension>
+
+ <extension
+ point="org.eclipse.ui.contexts">
+ <context
+ name="%contextName"
+ description="%contextDescription"
+ id="org.eclipse.acceleo.ide.ui.debug"
+ parentId="org.eclipse.debug.ui.debugging">
+ </context>
+ </extension>
+
+ <extension
+ point="org.eclipse.debug.ui.debugModelContextBindings">
+ <modelContextBinding
+ debugModelId="org.eclipse.acceleo.ide.ui.debug.model"
+ contextId="org.eclipse.acceleo.ide.ui.debug">
+ </modelContextBinding>
+ </extension>
+
+ <extension point="org.eclipse.core.runtime.contentTypes">
+ <content-type id="emtl" name="Acceleo AST File"
+ base-type="org.eclipse.jdt.core.javaClass"
+ priority="high"
+ file-extensions="emtl"/>
+ </extension>
+
+ <extension
+ point="org.eclipse.search.searchResultViewPages">
+ <viewPage
+ class="org.eclipse.acceleo.internal.ide.ui.editors.template.actions.references.ReferencesSearchViewPage"
+ id="org.eclipse.acceleo.internal.ide.ui.editors.template.actions.ReferencesSearchViewPage"
+ searchResultClass="org.eclipse.acceleo.internal.ide.ui.editors.template.actions.references.ReferencesSearchResult">
+ </viewPage>
+ </extension>
+
+ <extension
+ point="org.eclipse.ui.views">
+ <category
+ id="org.eclipse.acceleo.ide.ui"
+ name="Acceleo">
+ </category>
+ <view
+ category="org.eclipse.acceleo.ide.ui"
+ class="org.eclipse.acceleo.internal.ide.ui.views.result.AcceleoResultView"
+ icon="icons/AcceleoResultView.gif"
+ id="org.eclipse.acceleo.ide.ui.views.result.AcceleoResultView"
+ name="Acceleo Result">
+ </view>
+ </extension>
+
+ <extension
+ point="org.eclipse.ui.workbench.texteditor.hyperlinkDetectors">
+ <hyperlinkDetector
+ activate="true"
+ class="org.eclipse.acceleo.internal.ide.ui.editors.template.AcceleoElementHyperlinkDetector"
+ id="org.eclipse.acceleo.ide.ui.openDeclarationHyperlink"
+ name="Acceleo Open Declaration"
+ targetId="org.eclipse.acceleo.ide.ui.AcceleoTemplateSource">
+ </hyperlinkDetector>
+ </extension>
+
+ <extension
+ point="org.eclipse.ui.workbench.texteditor.hyperlinkDetectorTargets">
+ <target
+ id="org.eclipse.acceleo.ide.ui.AcceleoTemplateSource"
+ name="Acceleo Editor">
+ <context
+ type="org.eclipse.acceleo.internal.ide.ui.editors.template.AcceleoEditor">
+ </context>
+ </target>
+ </extension>
+</plugin>
diff --git a/plugins/org.eclipse.acceleo.ide.ui/schema/example.exsd b/plugins/org.eclipse.acceleo.ide.ui/schema/example.exsd
new file mode 100644
index 0000000..0f47648
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/schema/example.exsd
@@ -0,0 +1,104 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<schema targetNamespace="org.eclipse.acceleo.ide.ui">
+<annotation>
+ <appInfo>
+ <meta.schema plugin="org.eclipse.acceleo.ide.ui" id="example" name="org.eclipse.acceleo.ide.ui.example"/>
+ </appInfo>
+ <documentation>
+ Define a strategy to initialize automatically a file in the Acceleo project.
+ </documentation>
+ </annotation>
+
+ <element name="extension">
+ <complexType>
+ <sequence>
+ <element ref="strategy" minOccurs="1" maxOccurs="unbounded"/>
+ </sequence>
+ <attribute name="point" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="id" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ <appInfo>
+ <meta.attribute translatable="true"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <element name="strategy">
+ <complexType>
+ <attribute name="class" type="string" use="required">
+ <annotation>
+ <documentation>
+ The fully qualified name of a Java class implementing &lt;code&gt;org.eclipse.acceleo.ide.ui.wizards.newfile.example.IAcceleoExampleStrategy&lt;/code&gt;.
+ </documentation>
+ <appInfo>
+ <meta.attribute kind="java" basedOn="org.eclipse.acceleo.ide.ui.wizards.newfile.example.IAcceleoExampleStrategy"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="since"/>
+ </appInfo>
+ <documentation>
+
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="examples"/>
+ </appInfo>
+ <documentation>
+
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="apiInfo"/>
+ </appInfo>
+ <documentation>
+
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="implementation"/>
+ </appInfo>
+ <documentation>
+
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="copyright"/>
+ </appInfo>
+ <documentation>
+
+ </documentation>
+ </annotation>
+
+</schema>
diff --git a/plugins/org.eclipse.acceleo.ide.ui/schema/launching.exsd b/plugins/org.eclipse.acceleo.ide.ui/schema/launching.exsd
new file mode 100644
index 0000000..121cc73
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/schema/launching.exsd
@@ -0,0 +1,116 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<schema targetNamespace="org.eclipse.acceleo.ide.ui" xmlns="http://www.w3.org/2001/XMLSchema">
+<annotation>
+ <appinfo>
+ <meta.schema plugin="org.eclipse.acceleo.ide.ui" id="launching" name="org.eclipse.acceleo.ide.ui.launching"/>
+ </appinfo>
+ <documentation>
+ Define a strategy to launch an Acceleo file.
+ </documentation>
+ </annotation>
+
+ <element name="extension">
+ <annotation>
+ <appinfo>
+ <meta.element />
+ </appinfo>
+ </annotation>
+ <complexType>
+ <sequence>
+ <element ref="strategy" minOccurs="1" maxOccurs="unbounded"/>
+ </sequence>
+ <attribute name="point" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="id" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ <appinfo>
+ <meta.attribute translatable="true"/>
+ </appinfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <element name="strategy">
+ <complexType>
+ <attribute name="description" type="string" use="required">
+ <annotation>
+ <documentation>
+ The unique description of the strategy displayed in the Acceleo launch configuration.
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="class" type="string" use="required">
+ <annotation>
+ <documentation>
+ The fully qualified name of a Java class implementing &lt;code&gt;org.eclipse.acceleo.ide.ui.launching.strategy.IAcceleoLaunchingStrategy&lt;/code&gt;.
+ </documentation>
+ <appinfo>
+ <meta.attribute kind="java" basedOn="org.eclipse.acceleo.ide.ui.launching.strategy.IAcceleoLaunchingStrategy"/>
+ </appinfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="since"/>
+ </appInfo>
+ <documentation>
+
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="examples"/>
+ </appInfo>
+ <documentation>
+
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="apiInfo"/>
+ </appInfo>
+ <documentation>
+
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="implementation"/>
+ </appInfo>
+ <documentation>
+
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="copyright"/>
+ </appInfo>
+ <documentation>
+
+ </documentation>
+ </annotation>
+
+</schema>
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/builders/runner/CreateRunnableAntCallWriter.java b/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/builders/runner/CreateRunnableAntCallWriter.java
new file mode 100644
index 0000000..5f58502
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/builders/runner/CreateRunnableAntCallWriter.java
@@ -0,0 +1,44 @@
+package org.eclipse.acceleo.internal.ide.ui.builders.runner;
+
+public class CreateRunnableAntCallWriter
+{
+ protected static String nl;
+ public static synchronized CreateRunnableAntCallWriter create(String lineSeparator)
+ {
+ nl = lineSeparator;
+ CreateRunnableAntCallWriter result = new CreateRunnableAntCallWriter();
+ nl = null;
+ return result;
+ }
+
+ public final String NL = nl == null ? (System.getProperties().getProperty("line.separator")) : nl;
+ protected final String TEXT_1 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + NL + "" + NL + "<!-- Rename this file, put it in the target project and call it with \"External Tools > Run As > Ant Build\" -->" + NL + "<!-- You have to change the MODEL and the TARGET values -->" + NL + "" + NL + "<project basedir=\".\" default=\"";
+ protected final String TEXT_2 = "Sample\" name=\"";
+ protected final String TEXT_3 = "Sample\">" + NL + "\t<import file=\"../";
+ protected final String TEXT_4 = "/tasks/";
+ protected final String TEXT_5 = ".xml\"/>" + NL + "\t<property name=\"MODEL\" value=\"${basedir}/model/file.xmi\"/>" + NL + "\t<property name=\"TARGET\" value=\"${basedir}/src-gen\"/>" + NL + "\t<target name=\"";
+ protected final String TEXT_6 = "Sample\" description=\"Generate files in '${TARGET}'\">" + NL + "\t\t<antcall target=\"";
+ protected final String TEXT_7 = "\" >" + NL + "\t\t\t<param name=\"model\" value=\"${MODEL}\"/>" + NL + "\t\t\t<param name=\"target\" value=\"${TARGET}\"/>" + NL + "\t\t</antcall>" + NL + "\t</target>" + NL + "</project>";
+
+ public String generate(Object argument)
+ {
+ final StringBuffer stringBuffer = new StringBuffer();
+
+ CreateRunnableAcceleoContent content = (CreateRunnableAcceleoContent) argument;
+
+ stringBuffer.append(TEXT_1);
+ stringBuffer.append(content.getModuleFileShortName());
+ stringBuffer.append(TEXT_2);
+ stringBuffer.append(content.getProjectName());
+ stringBuffer.append(TEXT_3);
+ stringBuffer.append(content.getProjectName());
+ stringBuffer.append(TEXT_4);
+ stringBuffer.append(content.getModuleFileShortName());
+ stringBuffer.append(TEXT_5);
+ stringBuffer.append(content.getModuleFileShortName());
+ stringBuffer.append(TEXT_6);
+ stringBuffer.append(content.getModuleFileShortName());
+ stringBuffer.append(TEXT_7);
+ return stringBuffer.toString();
+ }
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/builders/runner/CreateRunnableAntWriter.java b/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/builders/runner/CreateRunnableAntWriter.java
new file mode 100644
index 0000000..54c2d8a
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/builders/runner/CreateRunnableAntWriter.java
@@ -0,0 +1,67 @@
+package org.eclipse.acceleo.internal.ide.ui.builders.runner;
+
+public class CreateRunnableAntWriter
+{
+ protected static String nl;
+ public static synchronized CreateRunnableAntWriter create(String lineSeparator)
+ {
+ nl = lineSeparator;
+ CreateRunnableAntWriter result = new CreateRunnableAntWriter();
+ nl = null;
+ return result;
+ }
+
+ public final String NL = nl == null ? (System.getProperties().getProperty("line.separator")) : nl;
+ protected final String TEXT_1 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + NL + "<project default=\"";
+ protected final String TEXT_2 = "\" name=\"";
+ protected final String TEXT_3 = "\">" + NL + " <property name=\"ECLIPSE_HOME\" value=\"../../\"/>" + NL + " <property name=\"ECLIPSE_WORKSPACE\" value=\"../\"/>" + NL + " <path id=\"";
+ protected final String TEXT_4 = ".libraryclasspath\">" + NL + " \t<pathelement location=\"../";
+ protected final String TEXT_5 = "/bin\"/>" + NL + " \t";
+ protected final String TEXT_6 = NL + " \t<pathelement location=\"";
+ protected final String TEXT_7 = "\"/>";
+ protected final String TEXT_8 = NL + " </path>" + NL + " <path id=\"";
+ protected final String TEXT_9 = ".classpath\">" + NL + " <path refid=\"";
+ protected final String TEXT_10 = ".libraryclasspath\"/>" + NL + " </path>" + NL + "" + NL + "\t<target name=\"";
+ protected final String TEXT_11 = "\">" + NL + "" + NL + "\t\t<java classname=\"";
+ protected final String TEXT_12 = ".";
+ protected final String TEXT_13 = "\" classpathref=\"";
+ protected final String TEXT_14 = ".classpath\">" + NL + "\t\t\t<arg value=\"${model}\"/>" + NL + "\t\t\t<arg value=\"${target}\"/>" + NL + "\t\t</java>" + NL + "" + NL + "\t</target>" + NL + "" + NL + "</project>";
+ protected final String TEXT_15 = NL;
+
+ public String generate(Object argument)
+ {
+ final StringBuffer stringBuffer = new StringBuffer();
+
+ CreateRunnableAcceleoContent content = (CreateRunnableAcceleoContent) argument;
+
+ stringBuffer.append(TEXT_1);
+ stringBuffer.append(content.getModuleFileShortName());
+ stringBuffer.append(TEXT_2);
+ stringBuffer.append(content.getProjectName());
+ stringBuffer.append(TEXT_3);
+ stringBuffer.append(content.getProjectName());
+ stringBuffer.append(TEXT_4);
+ stringBuffer.append(content.getProjectName());
+ stringBuffer.append(TEXT_5);
+ for (int i = 0; i < content.getResolvedClasspath().size(); i++) {
+ stringBuffer.append(TEXT_6);
+ stringBuffer.append(content.getResolvedClasspath().get(i));
+ stringBuffer.append(TEXT_7);
+ }
+ stringBuffer.append(TEXT_8);
+ stringBuffer.append(content.getProjectName());
+ stringBuffer.append(TEXT_9);
+ stringBuffer.append(content.getProjectName());
+ stringBuffer.append(TEXT_10);
+ stringBuffer.append(content.getModuleFileShortName());
+ stringBuffer.append(TEXT_11);
+ stringBuffer.append(content.getBasePackage());
+ stringBuffer.append(TEXT_12);
+ stringBuffer.append(content.getClassShortName());
+ stringBuffer.append(TEXT_13);
+ stringBuffer.append(content.getProjectName());
+ stringBuffer.append(TEXT_14);
+ stringBuffer.append(TEXT_15);
+ return stringBuffer.toString();
+ }
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/builders/runner/CreateRunnableJavaWriter.java b/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/builders/runner/CreateRunnableJavaWriter.java
new file mode 100644
index 0000000..60f6a6c
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/builders/runner/CreateRunnableJavaWriter.java
@@ -0,0 +1,81 @@
+package org.eclipse.acceleo.internal.ide.ui.builders.runner;
+
+public class CreateRunnableJavaWriter
+{
+ protected static String nl;
+ public static synchronized CreateRunnableJavaWriter create(String lineSeparator)
+ {
+ nl = lineSeparator;
+ CreateRunnableJavaWriter result = new CreateRunnableJavaWriter();
+ nl = null;
+ return result;
+ }
+
+ public final String NL = nl == null ? (System.getProperties().getProperty("line.separator")) : nl;
+ protected final String TEXT_1 = "/*******************************************************************************" + NL + " * Copyright (c) 2008, 2009 Obeo." + NL + " * All rights reserved. This program and the accompanying materials" + NL + " * are made available under the terms of the Eclipse Public License v1.0" + NL + " * which accompanies this distribution, and is available at" + NL + " * http://www.eclipse.org/legal/epl-v10.html" + NL + " * " + NL + " * Contributors:" + NL + " * Obeo - initial API and implementation" + NL + " *******************************************************************************/" + NL + "package ";
+ protected final String TEXT_2 = ";" + NL + "" + NL + "import java.io.File;" + NL + "import java.io.IOException;" + NL + "import java.net.URL;" + NL + "import java.util.HashMap;" + NL + "import java.util.Map;" + NL + "import java.util.List;" + NL + "import java.util.ArrayList;" + NL + "" + NL + "import org.eclipse.emf.common.util.URI;" + NL + "import org.eclipse.emf.ecore.EObject;" + NL + "import org.eclipse.emf.ecore.EPackage;" + NL + "import org.eclipse.emf.ecore.resource.Resource;" + NL + "import org.eclipse.emf.ecore.resource.ResourceSet;" + NL + "import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;" + NL + "import org.eclipse.emf.ecore.util.EcoreUtil;" + NL + "import org.eclipse.emf.ecore.xmi.XMLResource;" + NL + "import org.eclipse.emf.ecore.xmi.impl.EcoreResourceFactoryImpl;" + NL + "import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;" + NL + "import org.eclipse.acceleo.model.mtl.Module;" + NL + "import org.eclipse.acceleo.model.mtl.MtlPackage;" + NL + "import org.eclipse.acceleo.engine.service.AcceleoService;" + NL + "import org.eclipse.ocl.ecore.EcoreEnvironment;" + NL + "import org.eclipse.ocl.ecore.EcoreEnvironmentFactory;" + NL + "" + NL + "/**" + NL + " * Entry point of the '";
+ protected final String TEXT_3 = "' generation module." + NL + " * " + NL + " * @author <a href=\"mailto:jonathan.musset@obeo.fr\">Jonathan Musset</a>" + NL + " */" + NL + "public class ";
+ protected final String TEXT_4 = " {" + NL + "" + NL + "\t/**" + NL + "\t * The name of the module." + NL + "\t * @generated" + NL + "\t */" + NL + "\tpublic static final String MODULE_FILE_NAME = \"";
+ protected final String TEXT_5 = "\";" + NL + "\t" + NL + "\t/**" + NL + "\t * The name of the templates that are to be generated." + NL + "\t * @generated" + NL + "\t */" + NL + "\tpublic static final String[] TEMPLATE_NAMES = { ";
+ protected final String TEXT_6 = "\"";
+ protected final String TEXT_7 = "\", ";
+ protected final String TEXT_8 = "};" + NL + "" + NL + "\t/**" + NL + "\t * The root element of the module." + NL + "\t */" + NL + "\tprivate Module module;" + NL + "" + NL + "\t/**" + NL + "\t * The model." + NL + "\t */" + NL + "\tprivate EObject model;" + NL + "" + NL + "\t/**" + NL + "\t * The output folder." + NL + "\t */" + NL + "\tprivate File targetFolder;" + NL + "" + NL + "\t/**" + NL + "\t * The other arguments." + NL + "\t */" + NL + "\tList<? extends Object> arguments;" + NL + "" + NL + "\t/**" + NL + "\t * Constructor." + NL + "\t * " + NL + "\t * @param modelURI" + NL + "\t * is the URI of the model." + NL + "\t * @param targetFolder" + NL + "\t * is the output folder" + NL + "\t * @param arguments" + NL + "\t * are the other arguments" + NL + "\t * @throws IOException" + NL + "\t * Thrown when the output cannot be saved." + NL + "\t * @generated" + NL + "\t */" + NL + "\tpublic ";
+ protected final String TEXT_9 = "(URI modelURI, File targetFolder, List<? extends Object> arguments) throws IOException {" + NL + "\t\tResourceSet resourceSet = new ResourceSetImpl();" + NL + "\t\tregisterResourceFactories(resourceSet);" + NL + "\t\tregisterPackages(resourceSet);" + NL + "\t\tURL templateURL = ";
+ protected final String TEXT_10 = ".class.getResource(MODULE_FILE_NAME + \".emtl\");" + NL + "\t\tif (templateURL == null) {" + NL + "\t\t\tthrow new IOException(\"'\" + MODULE_FILE_NAME + \".emtl' not found\");" + NL + "\t\t} else {" + NL + "\t\t\tURI templateURI = createTemplateURI(templateURL.getPath());" + NL + "\t\t\tmodule = (Module)load(templateURI, resourceSet);" + NL + "\t\t\tmodel = load(modelURI, resourceSet);" + NL + "\t\t\tthis.targetFolder = targetFolder;" + NL + "\t\t\tthis.arguments = arguments;" + NL + "\t\t}" + NL + "\t}" + NL + "" + NL + "\t/**" + NL + "\t * Constructor." + NL + "\t * " + NL + "\t * @param model" + NL + "\t * is the root element of the model." + NL + "\t * @param targetFolder" + NL + "\t * is the output folder" + NL + "\t * @param arguments" + NL + "\t * are the other arguments" + NL + "\t * @throws IOException" + NL + "\t * Thrown when the output cannot be saved." + NL + "\t * @generated" + NL + "\t */" + NL + "\tpublic ";
+ protected final String TEXT_11 = "(EObject model, File targetFolder, List<? extends Object> arguments) throws IOException {" + NL + "\t\tResourceSet resourceSet = model.eResource().getResourceSet();" + NL + "\t\tregisterResourceFactories(resourceSet);" + NL + "\t\tregisterPackages(resourceSet);" + NL + "\t\tURL templateURL = ";
+ protected final String TEXT_12 = ".class.getResource(MODULE_FILE_NAME + \".emtl\");" + NL + "\t\tif (templateURL == null) {" + NL + "\t\t\tthrow new IOException(\"'\" + MODULE_FILE_NAME + \".emtl' not found\");" + NL + "\t\t} else {" + NL + "\t\t\tURI templateURI = createTemplateURI(templateURL.getPath());" + NL + "\t\t\tmodule = (Module)load(templateURI, resourceSet);" + NL + "\t\t\tthis.model = model;" + NL + "\t\t\tthis.targetFolder = targetFolder;" + NL + "\t\t\tthis.arguments = arguments;" + NL + "\t\t}" + NL + "\t}" + NL + "" + NL + "\t/**" + NL + "\t * Creates the template URI." + NL + "\t * " + NL + "\t * @param entry" + NL + "\t * is the local path of the EMTL file" + NL + "\t * @generated" + NL + "\t */" + NL + "\tprotected URI createTemplateURI(String entry) {" + NL + "\t\treturn URI.createFileURI(URI.decode(entry));" + NL + "\t}" + NL + "" + NL + "\t/**" + NL + "\t * Gets the model." + NL + "\t * @return the model root element" + NL + "\t */" + NL + "\tpublic EObject getModel() {" + NL + "\t\treturn model;" + NL + "\t}" + NL + "" + NL + "\t/**" + NL + "\t * Updates the registry used for looking up a package based namespace, in the resource set." + NL + "\t * " + NL + "\t * @param resourceSet" + NL + "\t * is the resource set" + NL + "\t * @generated" + NL + "\t */" + NL + "\tprivate void registerPackages(ResourceSet resourceSet) {";
+ protected final String TEXT_13 = NL + "\t\tresourceSet.getPackageRegistry().put(";
+ protected final String TEXT_14 = ".eINSTANCE.getNsURI(), ";
+ protected final String TEXT_15 = ".eINSTANCE);";
+ protected final String TEXT_16 = NL + "\t\tresourceSet.getPackageRegistry().put(org.eclipse.ocl.ecore.EcorePackage.eINSTANCE.getNsURI(), org.eclipse.ocl.ecore.EcorePackage.eINSTANCE);" + NL + "\t\tresourceSet.getPackageRegistry().put(org.eclipse.ocl.expressions.ExpressionsPackage.eINSTANCE.getNsURI(), org.eclipse.ocl.expressions.ExpressionsPackage.eINSTANCE);" + NL + "\t\tresourceSet.getPackageRegistry().put(MtlPackage.eINSTANCE.getNsURI(), MtlPackage.eINSTANCE);" + NL + "\t\tresourceSet.getPackageRegistry().put(\"http://www.eclipse.org/ocl/1.1.0/oclstdlib.ecore\", getOCLStdLibPackage());" + NL + "\t}" + NL + "\t" + NL + "\t/**" + NL + "\t * Returns the package containing the OCL standard library." + NL + "\t * " + NL + "\t * @return The package containing the OCL standard library." + NL + "\t * @generated" + NL + "\t */" + NL + "\tprivate EPackage getOCLStdLibPackage() {" + NL + "\t\tEcoreEnvironmentFactory factory = new EcoreEnvironmentFactory();" + NL + "\t\tEcoreEnvironment environment = (EcoreEnvironment)factory.createEnvironment();" + NL + "\t\treturn (EPackage)EcoreUtil.getRootContainer(environment.getOCLStandardLibrary().getBag());" + NL + "\t}" + NL + "\t" + NL + "\t/**" + NL + "\t * Updates the registry used for looking up resources factory in the given resource set." + NL + "\t *" + NL + "\t * @param resourceSet" + NL + "\t * The resource set that is to be updated." + NL + "\t * @generated" + NL + "\t */" + NL + "\tprivate void registerResourceFactories(ResourceSet resourceSet) {" + NL + "\t\tresourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put(\"ecore\", new EcoreResourceFactoryImpl());" + NL + "\t\tresourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put(\"emtl\", new org.eclipse.acceleo.model.mtl.resource.EMtlResourceFactoryImpl());" + NL + "\t\tresourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put(Resource.Factory.Registry.DEFAULT_EXTENSION, new XMIResourceFactoryImpl());" + NL + "\t}" + NL + "" + NL + "\t/**" + NL + "\t * The main method." + NL + "\t * " + NL + "\t * @param args" + NL + "\t * are the arguments" + NL + "\t * @generated" + NL + "\t */" + NL + "\tpublic static void main(String[] args) {" + NL + "\t\ttry {" + NL + "\t\t\tif (args.length < 2) {" + NL + "\t\t\t\tSystem.out.println(\"Arguments not valid : {model, folder}.\");" + NL + "\t\t\t} else {" + NL + "\t\t\t\tURI modelURI = URI.createFileURI(args[0]);" + NL + "\t\t\t\tFile folder = new File(args[1]);" + NL + "\t\t\t\tList<String> arguments = new ArrayList<String>();" + NL + "\t\t\t\tfor (int i = 2; i < args.length; i++) {" + NL + "\t\t\t\t\targuments.add(args[i]);" + NL + "\t\t\t\t}" + NL + "\t\t\t\t";
+ protected final String TEXT_17 = " generator = new ";
+ protected final String TEXT_18 = "(modelURI, folder, arguments);" + NL + "\t\t\t\tgenerator.doGenerate();" + NL + "\t\t\t}" + NL + "\t\t} catch (IOException e) {" + NL + "\t\t\te.printStackTrace();" + NL + "\t\t}" + NL + "\t}" + NL + "" + NL + "\t/**" + NL + "\t * Launches the generation." + NL + "\t * " + NL + "\t * @throws IOException" + NL + "\t * Thrown when the output cannot be saved." + NL + "\t * @generated" + NL + "\t */" + NL + "\tpublic void doGenerate() throws IOException {" + NL + "\t\tif (!targetFolder.exists()) {" + NL + "\t\t\ttargetFolder.mkdirs();" + NL + "\t\t}" + NL + "\t\tfor (int i = 0; i < TEMPLATE_NAMES.length; i++) {" + NL + "\t\t\tAcceleoService.doGenerate(module, TEMPLATE_NAMES[i], model, arguments, targetFolder, false);" + NL + "\t\t}" + NL + "\t}" + NL + "" + NL + "\t/**" + NL + "\t * Loads a model from an {@link org.eclipse.emf.common.util.URI URI} in a given {@link ResourceSet}." + NL + "\t * <p>" + NL + "\t * This will return the first root of the loaded model, other roots can be accessed via the resource's" + NL + "\t * content." + NL + "\t * </p>" + NL + "\t * " + NL + "\t * @param modelURI" + NL + "\t * {@link org.eclipse.emf.common.util.URI URI} where the model is stored." + NL + "\t * @param resourceSet" + NL + "\t * The {@link ResourceSet} to load the model in." + NL + "\t * @return The model loaded from the URI." + NL + "\t * @throws IOException" + NL + "\t * If the given file does not exist." + NL + "\t * @generated" + NL + "\t */" + NL + "\tprivate EObject load(URI modelURI, ResourceSet resourceSet) throws IOException {" + NL + "\t\tEObject result = null;" + NL + "\t\tfinal Resource modelResource = createResource(modelURI, resourceSet);" + NL + "\t\tfinal Map<String, String> options = new HashMap<String, String>();" + NL + "\t\toptions.put(XMLResource.OPTION_ENCODING, System.getProperty(\"file.encoding\"));" + NL + "\t\tmodelResource.load(options);" + NL + "\t\tif (modelResource.getContents().size() > 0) {" + NL + "\t\t\tresult = modelResource.getContents().get(0);" + NL + "\t\t}" + NL + "\t\treturn result;" + NL + "\t}" + NL + "" + NL + "\t/**" + NL + "\t * This will create a {@link Resource} given the model extension it is intended for and a ResourceSet." + NL + "\t * " + NL + "\t * @param modelURI" + NL + "\t * {@link org.eclipse.emf.common.util.URI URI} where the model is stored." + NL + "\t * @param resourceSet" + NL + "\t * The {@link ResourceSet} to load the model in." + NL + "\t * @return The {@link Resource} given the model extension it is intended for." + NL + "\t * @generated" + NL + "\t */" + NL + "\tprivate Resource createResource(URI modelURI, ResourceSet resourceSet) {" + NL + "\t\tString fileExtension = modelURI.fileExtension();" + NL + "\t\tif (fileExtension == null || fileExtension.length() == 0) {" + NL + "\t\t\tfileExtension = Resource.Factory.Registry.DEFAULT_EXTENSION;" + NL + "\t\t}" + NL + "\t\tfinal Resource.Factory.Registry registry = Resource.Factory.Registry.INSTANCE;" + NL + "\t\tfinal Object resourceFactory = registry.getExtensionToFactoryMap().get(fileExtension);" + NL + "\t\tif (resourceFactory != null) {" + NL + "\t\t\tresourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put(fileExtension," + NL + "\t\t\t\t\tresourceFactory);" + NL + "\t\t} else {" + NL + "\t\t\tresourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put(fileExtension," + NL + "\t\t\t\t\tnew XMIResourceFactoryImpl());" + NL + "\t\t}" + NL + "\t\treturn resourceSet.createResource(modelURI);" + NL + "\t}" + NL + "" + NL + "}";
+ protected final String TEXT_19 = NL;
+
+ public String generate(Object argument)
+ {
+ final StringBuffer stringBuffer = new StringBuffer();
+
+ CreateRunnableAcceleoContent content = (CreateRunnableAcceleoContent) argument;
+
+ stringBuffer.append(TEXT_1);
+ stringBuffer.append(content.getBasePackage());
+ stringBuffer.append(TEXT_2);
+ stringBuffer.append(content.getClassShortName());
+ stringBuffer.append(TEXT_3);
+ stringBuffer.append(content.getClassShortName());
+ stringBuffer.append(TEXT_4);
+ stringBuffer.append(content.getModuleFileShortName());
+ stringBuffer.append(TEXT_5);
+
+ for (int i = 0; i < content.getTemplateNames().size(); i++) {
+
+ stringBuffer.append(TEXT_6);
+ stringBuffer.append(content.getTemplateNames().get(i));
+ stringBuffer.append(TEXT_7);
+ }
+ stringBuffer.append(TEXT_8);
+ stringBuffer.append(content.getClassShortName());
+ stringBuffer.append(TEXT_9);
+ stringBuffer.append(content.getClassShortName());
+ stringBuffer.append(TEXT_10);
+ stringBuffer.append(content.getClassShortName());
+ stringBuffer.append(TEXT_11);
+ stringBuffer.append(content.getClassShortName());
+ stringBuffer.append(TEXT_12);
+ for (int i = 0; i < content.getPackages().size(); i++) {
+ stringBuffer.append(TEXT_13);
+ stringBuffer.append(content.getPackages().get(i));
+ stringBuffer.append(TEXT_14);
+ stringBuffer.append(content.getPackages().get(i));
+ stringBuffer.append(TEXT_15);
+ }
+ stringBuffer.append(TEXT_16);
+ stringBuffer.append(content.getClassShortName());
+ stringBuffer.append(TEXT_17);
+ stringBuffer.append(content.getClassShortName());
+ stringBuffer.append(TEXT_18);
+ stringBuffer.append(TEXT_19);
+ return stringBuffer.toString();
+ }
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleActivatorWriter.java b/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleActivatorWriter.java
new file mode 100644
index 0000000..31f622e
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleActivatorWriter.java
@@ -0,0 +1,34 @@
+package org.eclipse.acceleo.internal.ide.ui.wizards.newproject;
+
+public class CreateModuleActivatorWriter
+{
+ protected static String nl;
+ public static synchronized CreateModuleActivatorWriter create(String lineSeparator)
+ {
+ nl = lineSeparator;
+ CreateModuleActivatorWriter result = new CreateModuleActivatorWriter();
+ nl = null;
+ return result;
+ }
+
+ public final String NL = nl == null ? (System.getProperties().getProperty("line.separator")) : nl;
+ protected final String TEXT_1 = "/*******************************************************************************" + NL + " * Copyright (c) 2008, 2009 Obeo." + NL + " * All rights reserved. This program and the accompanying materials" + NL + " * are made available under the terms of the Eclipse Public License v1.0" + NL + " * which accompanies this distribution, and is available at" + NL + " * http://www.eclipse.org/legal/epl-v10.html" + NL + " * " + NL + " * Contributors:" + NL + " * Obeo - initial API and implementation" + NL + " *******************************************************************************/" + NL + "package ";
+ protected final String TEXT_2 = ";" + NL + "" + NL + "import org.eclipse.core.runtime.Plugin;" + NL + "import org.osgi.framework.BundleContext;" + NL + "" + NL + "/**" + NL + " * The activator class controls the plug-in life cycle." + NL + " * " + NL + " * @author <a href=\"mailto:jonathan.musset@obeo.fr\">Jonathan Musset</a>" + NL + " */" + NL + "public class Activator extends Plugin {" + NL + "" + NL + "\t/**" + NL + "\t * The plug-in ID." + NL + "\t */" + NL + "\tpublic static final String PLUGIN_ID = \"";
+ protected final String TEXT_3 = "\";" + NL + "" + NL + "\t/**" + NL + "\t * The shared instance." + NL + "\t */" + NL + "\tprivate static Activator plugin;" + NL + "\t" + NL + "\t/**" + NL + "\t * The constructor." + NL + "\t */" + NL + "\tpublic Activator() {" + NL + "\t}" + NL + "" + NL + "\t/**{@inheritDoc}" + NL + "\t *" + NL + "\t * @see org.eclipse.core.runtime.Plugin#start(org.osgi.framework.BundleContext)" + NL + "\t */" + NL + "\tpublic void start(BundleContext context) throws Exception {" + NL + "\t\tsuper.start(context);" + NL + "\t\tplugin = this;" + NL + "\t}" + NL + "" + NL + "\t/**{@inheritDoc}" + NL + "\t *" + NL + "\t * @see org.eclipse.core.runtime.Plugin#stop(org.osgi.framework.BundleContext)" + NL + "\t */" + NL + "\tpublic void stop(BundleContext context) throws Exception {" + NL + "\t\tplugin = null;" + NL + "\t\tsuper.stop(context);" + NL + "\t}" + NL + "" + NL + "\t/**" + NL + "\t * Returns the shared instance." + NL + "\t *" + NL + "\t * @return the shared instance" + NL + "\t */" + NL + "\tpublic static Activator getDefault() {" + NL + "\t\treturn plugin;" + NL + "\t}" + NL + "" + NL + "}";
+ protected final String TEXT_4 = NL;
+
+ public String generate(Object argument)
+ {
+ final StringBuffer stringBuffer = new StringBuffer();
+
+ CreateModuleData content = (CreateModuleData) argument;
+
+ stringBuffer.append(TEXT_1);
+ stringBuffer.append(content.getProjectName());
+ stringBuffer.append(TEXT_2);
+ stringBuffer.append(content.getProjectName());
+ stringBuffer.append(TEXT_3);
+ stringBuffer.append(TEXT_4);
+ return stringBuffer.toString();
+ }
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleBuildWriter.java b/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleBuildWriter.java
new file mode 100644
index 0000000..267f2d5
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleBuildWriter.java
@@ -0,0 +1,25 @@
+package org.eclipse.acceleo.internal.ide.ui.wizards.newproject;
+
+public class CreateModuleBuildWriter
+{
+ protected static String nl;
+ public static synchronized CreateModuleBuildWriter create(String lineSeparator)
+ {
+ nl = lineSeparator;
+ CreateModuleBuildWriter result = new CreateModuleBuildWriter();
+ nl = null;
+ return result;
+ }
+
+ public final String NL = nl == null ? (System.getProperties().getProperty("line.separator")) : nl;
+ protected final String TEXT_1 = "source.. = src/" + NL + "output.. = bin/" + NL + "bin.includes = META-INF/,\\" + NL + " ." + NL;
+ protected final String TEXT_2 = NL;
+
+ public String generate(Object argument)
+ {
+ final StringBuffer stringBuffer = new StringBuffer();
+ stringBuffer.append(TEXT_1);
+ stringBuffer.append(TEXT_2);
+ return stringBuffer.toString();
+ }
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleClasspathWriter.java b/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleClasspathWriter.java
new file mode 100644
index 0000000..7bb7281
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleClasspathWriter.java
@@ -0,0 +1,25 @@
+package org.eclipse.acceleo.internal.ide.ui.wizards.newproject;
+
+public class CreateModuleClasspathWriter
+{
+ protected static String nl;
+ public static synchronized CreateModuleClasspathWriter create(String lineSeparator)
+ {
+ nl = lineSeparator;
+ CreateModuleClasspathWriter result = new CreateModuleClasspathWriter();
+ nl = null;
+ return result;
+ }
+
+ public final String NL = nl == null ? (System.getProperties().getProperty("line.separator")) : nl;
+ protected final String TEXT_1 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + NL + "<classpath>" + NL + "\t<classpathentry kind=\"con\" path=\"org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5\"/>" + NL + "\t<classpathentry kind=\"con\" path=\"org.eclipse.pde.core.requiredPlugins\"/>" + NL + "\t<classpathentry kind=\"src\" path=\"src\"/>" + NL + "\t<classpathentry kind=\"output\" path=\"bin\"/>" + NL + "</classpath>";
+ protected final String TEXT_2 = NL;
+
+ public String generate(Object argument)
+ {
+ final StringBuffer stringBuffer = new StringBuffer();
+ stringBuffer.append(TEXT_1);
+ stringBuffer.append(TEXT_2);
+ return stringBuffer.toString();
+ }
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleMANIFESTWriter.java b/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleMANIFESTWriter.java
new file mode 100644
index 0000000..478e1a4
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleMANIFESTWriter.java
@@ -0,0 +1,47 @@
+package org.eclipse.acceleo.internal.ide.ui.wizards.newproject;
+
+public class CreateModuleMANIFESTWriter
+{
+ protected static String nl;
+ public static synchronized CreateModuleMANIFESTWriter create(String lineSeparator)
+ {
+ nl = lineSeparator;
+ CreateModuleMANIFESTWriter result = new CreateModuleMANIFESTWriter();
+ nl = null;
+ return result;
+ }
+
+ public final String NL = nl == null ? (System.getProperties().getProperty("line.separator")) : nl;
+ protected final String TEXT_1 = "Manifest-Version: 1.0" + NL + "Bundle-ManifestVersion: 2" + NL + "Bundle-Name: Acceleo ";
+ protected final String TEXT_2 = " Module Runtime Plug-in" + NL + "Bundle-SymbolicName: ";
+ protected final String TEXT_3 = NL + "Bundle-Version: 1.0.0.qualifier" + NL + "Bundle-Activator: ";
+ protected final String TEXT_4 = ".Activator" + NL + "Bundle-Vendor: Eclipse.org" + NL + "Require-Bundle: org.eclipse.core.runtime, ";
+ protected final String TEXT_5 = NL + " ";
+ protected final String TEXT_6 = ",";
+ protected final String TEXT_7 = NL + " org.eclipse.emf.ecore," + NL + " org.eclipse.emf.ecore.xmi," + NL + " org.eclipse.ocl," + NL + " org.eclipse.ocl.ecore," + NL + " org.eclipse.acceleo.model," + NL + " org.eclipse.acceleo.engine" + NL + "Bundle-RequiredExecutionEnvironment: J2SE-1.5" + NL + "Bundle-ActivationPolicy: lazy";
+ protected final String TEXT_8 = NL;
+
+ public String generate(Object argument)
+ {
+ final StringBuffer stringBuffer = new StringBuffer();
+
+ CreateModuleData content = (CreateModuleData) argument;
+
+ stringBuffer.append(TEXT_1);
+ stringBuffer.append(content.getModuleName());
+ stringBuffer.append(TEXT_2);
+ stringBuffer.append(content.getProjectName());
+ stringBuffer.append(TEXT_3);
+ stringBuffer.append(content.getProjectName());
+ stringBuffer.append(TEXT_4);
+
+ for (int i = 0; i < content.getPluginDependencies().size(); i++) {
+ stringBuffer.append(TEXT_5);
+ stringBuffer.append(content.getPluginDependencies().get(i));
+ stringBuffer.append(TEXT_6);
+ }
+ stringBuffer.append(TEXT_7);
+ stringBuffer.append(TEXT_8);
+ return stringBuffer.toString();
+ }
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleProjectWriter.java b/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleProjectWriter.java
new file mode 100644
index 0000000..05ab758
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleProjectWriter.java
@@ -0,0 +1,31 @@
+package org.eclipse.acceleo.internal.ide.ui.wizards.newproject;
+
+public class CreateModuleProjectWriter
+{
+ protected static String nl;
+ public static synchronized CreateModuleProjectWriter create(String lineSeparator)
+ {
+ nl = lineSeparator;
+ CreateModuleProjectWriter result = new CreateModuleProjectWriter();
+ nl = null;
+ return result;
+ }
+
+ public final String NL = nl == null ? (System.getProperties().getProperty("line.separator")) : nl;
+ protected final String TEXT_1 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + NL + "<projectDescription>" + NL + "\t<name>";
+ protected final String TEXT_2 = "</name>" + NL + "\t<comment></comment>" + NL + "\t<projects>" + NL + "\t</projects>" + NL + "\t<buildSpec>" + NL + "\t\t<buildCommand>" + NL + "\t\t\t<name>org.eclipse.jdt.core.javabuilder</name>" + NL + "\t\t\t<arguments>" + NL + "\t\t\t</arguments>" + NL + "\t\t</buildCommand>" + NL + "\t\t<buildCommand>" + NL + "\t\t\t<name>org.eclipse.pde.ManifestBuilder</name>" + NL + "\t\t\t<arguments>" + NL + "\t\t\t</arguments>" + NL + "\t\t</buildCommand>" + NL + "\t\t<buildCommand>" + NL + "\t\t\t<name>org.eclipse.pde.SchemaBuilder</name>" + NL + "\t\t\t<arguments>" + NL + "\t\t\t</arguments>" + NL + "\t\t</buildCommand>" + NL + "\t\t<buildCommand>" + NL + "\t\t\t<name>org.eclipse.acceleo.ide.ui.acceleoBuilder</name>" + NL + "\t\t\t<arguments>" + NL + "\t\t\t</arguments>" + NL + "\t\t</buildCommand>" + NL + "\t</buildSpec>" + NL + "\t<natures>" + NL + "\t\t<nature>org.eclipse.acceleo.ide.ui.acceleoNature</nature>" + NL + "\t\t<nature>org.eclipse.pde.PluginNature</nature>" + NL + "\t\t<nature>org.eclipse.jdt.core.javanature</nature>" + NL + "\t</natures>" + NL + "</projectDescription>";
+ protected final String TEXT_3 = NL;
+
+ public String generate(Object argument)
+ {
+ final StringBuffer stringBuffer = new StringBuffer();
+
+ CreateModuleData content = (CreateModuleData) argument;
+
+ stringBuffer.append(TEXT_1);
+ stringBuffer.append(content.getProjectName());
+ stringBuffer.append(TEXT_2);
+ stringBuffer.append(TEXT_3);
+ return stringBuffer.toString();
+ }
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleSettingsWriter.java b/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleSettingsWriter.java
new file mode 100644
index 0000000..8fffb80
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleSettingsWriter.java
@@ -0,0 +1,25 @@
+package org.eclipse.acceleo.internal.ide.ui.wizards.newproject;
+
+public class CreateModuleSettingsWriter
+{
+ protected static String nl;
+ public static synchronized CreateModuleSettingsWriter create(String lineSeparator)
+ {
+ nl = lineSeparator;
+ CreateModuleSettingsWriter result = new CreateModuleSettingsWriter();
+ nl = null;
+ return result;
+ }
+
+ public final String NL = nl == null ? (System.getProperties().getProperty("line.separator")) : nl;
+ protected final String TEXT_1 = "eclipse.preferences.version=1" + NL + "org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5" + NL + "org.eclipse.jdt.core.compiler.compliance=1.5" + NL + "org.eclipse.jdt.core.compiler.problem.assertIdentifier=error" + NL + "org.eclipse.jdt.core.compiler.problem.enumIdentifier=error" + NL + "org.eclipse.jdt.core.compiler.source=1.5";
+ protected final String TEXT_2 = NL;
+
+ public String generate(Object argument)
+ {
+ final StringBuffer stringBuffer = new StringBuffer();
+ stringBuffer.append(TEXT_1);
+ stringBuffer.append(TEXT_2);
+ return stringBuffer.toString();
+ }
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleUIActivatorWriter.java b/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleUIActivatorWriter.java
new file mode 100644
index 0000000..0a7a23c
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleUIActivatorWriter.java
@@ -0,0 +1,34 @@
+package org.eclipse.acceleo.internal.ide.ui.wizards.newproject;
+
+public class CreateModuleUIActivatorWriter
+{
+ protected static String nl;
+ public static synchronized CreateModuleUIActivatorWriter create(String lineSeparator)
+ {
+ nl = lineSeparator;
+ CreateModuleUIActivatorWriter result = new CreateModuleUIActivatorWriter();
+ nl = null;
+ return result;
+ }
+
+ public final String NL = nl == null ? (System.getProperties().getProperty("line.separator")) : nl;
+ protected final String TEXT_1 = "/*******************************************************************************" + NL + " * Copyright (c) 2008, 2009 Obeo." + NL + " * All rights reserved. This program and the accompanying materials" + NL + " * are made available under the terms of the Eclipse Public License v1.0" + NL + " * which accompanies this distribution, and is available at" + NL + " * http://www.eclipse.org/legal/epl-v10.html" + NL + " * " + NL + " * Contributors:" + NL + " * Obeo - initial API and implementation" + NL + " *******************************************************************************/" + NL + "package ";
+ protected final String TEXT_2 = ";" + NL + "" + NL + "import org.eclipse.ui.plugin.AbstractUIPlugin;" + NL + "import org.osgi.framework.BundleContext;" + NL + "" + NL + "/**" + NL + " * The activator class controls the plug-in life cycle." + NL + " * " + NL + " * @author <a href=\"mailto:jonathan.musset@obeo.fr\">Jonathan Musset</a>" + NL + " */" + NL + "public class Activator extends AbstractUIPlugin {" + NL + "" + NL + "\t/**" + NL + "\t * The plug-in ID." + NL + "\t */" + NL + "\tpublic static final String PLUGIN_ID = \"";
+ protected final String TEXT_3 = "\";" + NL + "" + NL + "\t/**" + NL + "\t * The shared instance." + NL + "\t */" + NL + "\tprivate static Activator plugin;" + NL + "\t" + NL + "\t/**" + NL + "\t * The constructor." + NL + "\t */" + NL + "\tpublic Activator() {" + NL + "\t}" + NL + "" + NL + "\t/**{@inheritDoc}" + NL + "\t *" + NL + "\t * @see org.eclipse.core.runtime.Plugin#start(org.osgi.framework.BundleContext)" + NL + "\t * @generated" + NL + "\t */" + NL + "\tpublic void start(BundleContext context) throws Exception {" + NL + "\t\tsuper.start(context);" + NL + "\t\tplugin = this;" + NL + "\t}" + NL + "" + NL + "\t/**{@inheritDoc}" + NL + "\t *" + NL + "\t * @see org.eclipse.core.runtime.Plugin#stop(org.osgi.framework.BundleContext)" + NL + "\t * @generated" + NL + "\t */" + NL + "\tpublic void stop(BundleContext context) throws Exception {" + NL + "\t\tplugin = null;" + NL + "\t\tsuper.stop(context);" + NL + "\t}" + NL + "" + NL + "\t/**" + NL + "\t * Returns the shared instance." + NL + "\t *" + NL + "\t * @return the shared instance" + NL + "\t */" + NL + "\tpublic static Activator getDefault() {" + NL + "\t\treturn plugin;" + NL + "\t}" + NL + "" + NL + "}";
+ protected final String TEXT_4 = NL;
+
+ public String generate(Object argument)
+ {
+ final StringBuffer stringBuffer = new StringBuffer();
+
+ CreateModuleUIData content = (CreateModuleUIData) argument;
+
+ stringBuffer.append(TEXT_1);
+ stringBuffer.append(content.getProjectName());
+ stringBuffer.append(TEXT_2);
+ stringBuffer.append(content.getProjectName());
+ stringBuffer.append(TEXT_3);
+ stringBuffer.append(TEXT_4);
+ return stringBuffer.toString();
+ }
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleUIBuildWriter.java b/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleUIBuildWriter.java
new file mode 100644
index 0000000..7815714
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleUIBuildWriter.java
@@ -0,0 +1,25 @@
+package org.eclipse.acceleo.internal.ide.ui.wizards.newproject;
+
+public class CreateModuleUIBuildWriter
+{
+ protected static String nl;
+ public static synchronized CreateModuleUIBuildWriter create(String lineSeparator)
+ {
+ nl = lineSeparator;
+ CreateModuleUIBuildWriter result = new CreateModuleUIBuildWriter();
+ nl = null;
+ return result;
+ }
+
+ public final String NL = nl == null ? (System.getProperties().getProperty("line.separator")) : nl;
+ protected final String TEXT_1 = "source.. = src/" + NL + "output.. = bin/" + NL + "bin.includes = META-INF/,\\" + NL + " .,\\" + NL + " plugin.xml,\\" + NL + " icons/" + NL;
+ protected final String TEXT_2 = NL;
+
+ public String generate(Object argument)
+ {
+ final StringBuffer stringBuffer = new StringBuffer();
+ stringBuffer.append(TEXT_1);
+ stringBuffer.append(TEXT_2);
+ return stringBuffer.toString();
+ }
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleUIClasspathWriter.java b/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleUIClasspathWriter.java
new file mode 100644
index 0000000..3ce6a91
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleUIClasspathWriter.java
@@ -0,0 +1,25 @@
+package org.eclipse.acceleo.internal.ide.ui.wizards.newproject;
+
+public class CreateModuleUIClasspathWriter
+{
+ protected static String nl;
+ public static synchronized CreateModuleUIClasspathWriter create(String lineSeparator)
+ {
+ nl = lineSeparator;
+ CreateModuleUIClasspathWriter result = new CreateModuleUIClasspathWriter();
+ nl = null;
+ return result;
+ }
+
+ public final String NL = nl == null ? (System.getProperties().getProperty("line.separator")) : nl;
+ protected final String TEXT_1 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + NL + "<classpath>" + NL + "\t<classpathentry kind=\"con\" path=\"org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5\"/>" + NL + "\t<classpathentry kind=\"con\" path=\"org.eclipse.pde.core.requiredPlugins\"/>" + NL + "\t<classpathentry kind=\"src\" path=\"src\"/>" + NL + "\t<classpathentry kind=\"output\" path=\"bin\"/>" + NL + "</classpath>";
+ protected final String TEXT_2 = NL;
+
+ public String generate(Object argument)
+ {
+ final StringBuffer stringBuffer = new StringBuffer();
+ stringBuffer.append(TEXT_1);
+ stringBuffer.append(TEXT_2);
+ return stringBuffer.toString();
+ }
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleUIGenerateAllWriter.java b/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleUIGenerateAllWriter.java
new file mode 100644
index 0000000..ed30d79
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleUIGenerateAllWriter.java
@@ -0,0 +1,94 @@
+package org.eclipse.acceleo.internal.ide.ui.wizards.newproject;
+
+public class CreateModuleUIGenerateAllWriter
+{
+ protected static String nl;
+ public static synchronized CreateModuleUIGenerateAllWriter create(String lineSeparator)
+ {
+ nl = lineSeparator;
+ CreateModuleUIGenerateAllWriter result = new CreateModuleUIGenerateAllWriter();
+ nl = null;
+ return result;
+ }
+
+ public final String NL = nl == null ? (System.getProperties().getProperty("line.separator")) : nl;
+ protected final String TEXT_1 = "/*******************************************************************************" + NL + " * Copyright (c) 2008, 2009 Obeo." + NL + " * All rights reserved. This program and the accompanying materials" + NL + " * are made available under the terms of the Eclipse Public License v1.0" + NL + " * which accompanies this distribution, and is available at" + NL + " * http://www.eclipse.org/legal/epl-v10.html" + NL + " * " + NL + " * Contributors:" + NL + " * Obeo - initial API and implementation" + NL + " *******************************************************************************/" + NL + "package ";
+ protected final String TEXT_2 = ".common;" + NL + "" + NL + "import java.io.File;" + NL + "import java.io.IOException;" + NL + "import java.net.URL;" + NL + "import java.util.Enumeration;" + NL + "import java.util.List;" + NL + "" + NL + "import org.eclipse.core.runtime.IPath;" + NL + "import org.eclipse.core.runtime.Path;" + NL + "import org.eclipse.core.runtime.Platform;" + NL + "import org.eclipse.emf.common.util.URI;";
+ protected final String TEXT_3 = NL + "import org.eclipse.emf.ecore.EObject;";
+ protected final String TEXT_4 = NL + "import org.osgi.framework.Bundle;" + NL + "" + NL + "" + NL + "/**" + NL + " * Main entry point of the '";
+ protected final String TEXT_5 = "' generation module." + NL + " * " + NL + " * @author <a href=\"mailto:jonathan.musset@obeo.fr\">Jonathan Musset</a>" + NL + " */" + NL + "public class GenerateAll {" + NL + "" + NL + "\t/**" + NL + "\t * The model URI." + NL + "\t */" + NL + "\tprivate URI modelURI;" + NL + "" + NL + "\t/**" + NL + "\t * The output folder." + NL + "\t */" + NL + "\tprivate File targetFolder;" + NL + "" + NL + "\t/**" + NL + "\t * The other arguments." + NL + "\t */" + NL + "\tList<? extends Object> arguments;" + NL + "" + NL + "\t/**" + NL + "\t * Constructor." + NL + "\t * " + NL + "\t * @param modelURI" + NL + "\t * is the URI of the model." + NL + "\t * @param targetFolder" + NL + "\t * is the output folder" + NL + "\t * @param arguments" + NL + "\t * are the other arguments" + NL + "\t * @throws IOException" + NL + "\t * Thrown when the output cannot be saved." + NL + "\t * @generated" + NL + "\t */" + NL + "\tpublic GenerateAll(URI modelURI, File targetFolder, List<? extends Object> arguments) {" + NL + "\t\tthis.modelURI = modelURI;" + NL + "\t\tthis.targetFolder = targetFolder;" + NL + "\t\tthis.arguments = arguments;" + NL + "\t}" + NL + "" + NL + "\t/**" + NL + "\t * Launches the generation." + NL + "\t * " + NL + "\t * @throws IOException" + NL + "\t * Thrown when the output cannot be saved." + NL + "\t * @generated" + NL + "\t */" + NL + "\tpublic void doGenerate() throws IOException {" + NL + "\t\tif (!targetFolder.exists()) {" + NL + "\t\t\ttargetFolder.mkdirs();" + NL + "\t\t}" + NL + "\t\t";
+ protected final String TEXT_6 = NL + "\t\tfinal URI template0 = getTemplateURI(\"";
+ protected final String TEXT_7 = "\", new Path(\"";
+ protected final String TEXT_8 = "\"));" + NL + "\t\t";
+ protected final String TEXT_9 = " gen0 = new ";
+ protected final String TEXT_10 = "(modelURI, targetFolder, arguments) {" + NL + "\t\t\tprotected URI createTemplateURI(String entry) {" + NL + "\t\t\t\treturn template0;" + NL + "\t\t\t}" + NL + "\t\t};" + NL + "\t\tgen0.doGenerate();" + NL + "\t\t\t";
+ protected final String TEXT_11 = NL + "\t\tEObject model = gen0.getModel();" + NL + "\t\tif (model != null) {" + NL + "\t\t\t\t";
+ protected final String TEXT_12 = NL + "\t\t\tfinal URI template";
+ protected final String TEXT_13 = " = getTemplateURI(\"";
+ protected final String TEXT_14 = "\", new Path(\"";
+ protected final String TEXT_15 = "\"));" + NL + "\t\t\t";
+ protected final String TEXT_16 = " gen";
+ protected final String TEXT_17 = " = new ";
+ protected final String TEXT_18 = "(model, targetFolder, arguments) {" + NL + "\t\t\t\tprotected URI createTemplateURI(String entry) {" + NL + "\t\t\t\t\treturn template";
+ protected final String TEXT_19 = ";" + NL + "\t\t\t\t}" + NL + "\t\t\t};" + NL + "\t\t\tgen";
+ protected final String TEXT_20 = ".doGenerate();";
+ protected final String TEXT_21 = NL + "\t\t}" + NL + "\t\t\t";
+ protected final String TEXT_22 = NL + "\t\t";
+ protected final String TEXT_23 = NL + "\t}" + NL + "\t" + NL + "\t/**" + NL + "\t * Finds the template in the plug-in. Returns the template plug-in URI." + NL + "\t * " + NL + "\t * @param bundleID" + NL + "\t * is the plug-in ID" + NL + "\t * @param relativePath" + NL + "\t * is the relative path of the template in the plug-in" + NL + "\t * @return the template URI" + NL + "\t * @throws IOException" + NL + "\t * @generated" + NL + "\t */" + NL + "\t@SuppressWarnings(\"unchecked\")" + NL + "\tprivate URI getTemplateURI(String bundleID, IPath relativePath) throws IOException {" + NL + "\t\tBundle bundle = Platform.getBundle(bundleID);" + NL + "\t\tif (bundle == null) {" + NL + "\t\t\t// no need to go any further" + NL + "\t\t\treturn URI.createPlatformResourceURI(new Path(bundleID).append(relativePath).toString(), false);" + NL + "\t\t}" + NL + "\t\tURL url = bundle.getEntry(relativePath.toString());" + NL + "\t\tif (url == null && relativePath.segmentCount() > 1) {" + NL + "\t\t\tEnumeration<URL> entries = bundle.findEntries(\"/\", \"*.emtl\", true);" + NL + "\t\t\tif (entries != null) {" + NL + "\t\t\t\tString[] segmentsRelativePath = relativePath.segments();" + NL + "\t\t\t\twhile (url == null && entries.hasMoreElements()) {" + NL + "\t\t\t\t\tURL entry = entries.nextElement();" + NL + "\t\t\t\t\tIPath path = new Path(entry.getPath());" + NL + "\t\t\t\t\tif (path.segmentCount() > relativePath.segmentCount()) {" + NL + "\t\t\t\t\t\tpath = path.removeFirstSegments(path.segmentCount() - relativePath.segmentCount());" + NL + "\t\t\t\t\t}" + NL + "\t\t\t\t\tString[] segmentsPath = path.segments();" + NL + "\t\t\t\t\tboolean equals = segmentsPath.length == segmentsRelativePath.length;" + NL + "\t\t\t\t\tfor (int i = 0; equals && i < segmentsPath.length; i++) {" + NL + "\t\t\t\t\t\tequals = segmentsPath[i].equals(segmentsRelativePath[i]);" + NL + "\t\t\t\t\t}" + NL + "\t\t\t\t\tif (equals) {" + NL + "\t\t\t\t\t\turl = bundle.getEntry(entry.getPath());" + NL + "\t\t\t\t\t}" + NL + "\t\t\t\t}" + NL + "\t\t\t}" + NL + "\t\t}" + NL + "\t\tURI result;" + NL + "\t\tif (url != null) {" + NL + "\t\t\tresult = URI.createPlatformPluginURI(new Path(bundleID).append(new Path(url.getPath())).toString(), false);" + NL + "\t\t} else {" + NL + "\t\t\tresult = URI.createPlatformResourceURI(new Path(bundleID).append(relativePath).toString(), false);" + NL + "\t\t}" + NL + "\t\treturn result;" + NL + "\t}" + NL + "" + NL + "}";
+ protected final String TEXT_24 = NL;
+
+ public String generate(Object argument)
+ {
+ final StringBuffer stringBuffer = new StringBuffer();
+
+ CreateModuleUIData content = (CreateModuleUIData) argument;
+
+ stringBuffer.append(TEXT_1);
+ stringBuffer.append(content.getProjectName());
+ stringBuffer.append(TEXT_2);
+ if (content.getModuleJavaClasses().size() > 1) {
+ stringBuffer.append(TEXT_3);
+ }
+ stringBuffer.append(TEXT_4);
+ stringBuffer.append(content.getModuleNameWithSpaces());
+ stringBuffer.append(TEXT_5);
+ if (content.getModuleJavaClasses().size() > 0) {
+ stringBuffer.append(TEXT_6);
+ stringBuffer.append(content.getModuleTemplatesPlugins().get(0));
+ stringBuffer.append(TEXT_7);
+ stringBuffer.append(content.getModuleTemplates().get(0));
+ stringBuffer.append(TEXT_8);
+ stringBuffer.append(content.getModuleJavaClasses().get(0));
+ stringBuffer.append(TEXT_9);
+ stringBuffer.append(content.getModuleJavaClasses().get(0));
+ stringBuffer.append(TEXT_10);
+ if (content.getModuleJavaClasses().size() > 1) {
+ stringBuffer.append(TEXT_11);
+ for (int i = 1; i < content.getModuleJavaClasses().size(); i++) {
+ stringBuffer.append(TEXT_12);
+ stringBuffer.append(i);
+ stringBuffer.append(TEXT_13);
+ stringBuffer.append(content.getModuleTemplatesPlugins().get(i));
+ stringBuffer.append(TEXT_14);
+ stringBuffer.append(content.getModuleTemplates().get(i));
+ stringBuffer.append(TEXT_15);
+ stringBuffer.append(content.getModuleJavaClasses().get(i));
+ stringBuffer.append(TEXT_16);
+ stringBuffer.append(i);
+ stringBuffer.append(TEXT_17);
+ stringBuffer.append(content.getModuleJavaClasses().get(i));
+ stringBuffer.append(TEXT_18);
+ stringBuffer.append(i);
+ stringBuffer.append(TEXT_19);
+ stringBuffer.append(i);
+ stringBuffer.append(TEXT_20);
+ }
+ stringBuffer.append(TEXT_21);
+ }
+ stringBuffer.append(TEXT_22);
+ }
+ stringBuffer.append(TEXT_23);
+ stringBuffer.append(TEXT_24);
+ return stringBuffer.toString();
+ }
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleUIMANIFESTWriter.java b/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleUIMANIFESTWriter.java
new file mode 100644
index 0000000..4ec9aa0
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleUIMANIFESTWriter.java
@@ -0,0 +1,47 @@
+package org.eclipse.acceleo.internal.ide.ui.wizards.newproject;
+
+public class CreateModuleUIMANIFESTWriter
+{
+ protected static String nl;
+ public static synchronized CreateModuleUIMANIFESTWriter create(String lineSeparator)
+ {
+ nl = lineSeparator;
+ CreateModuleUIMANIFESTWriter result = new CreateModuleUIMANIFESTWriter();
+ nl = null;
+ return result;
+ }
+
+ public final String NL = nl == null ? (System.getProperties().getProperty("line.separator")) : nl;
+ protected final String TEXT_1 = "Manifest-Version: 1.0" + NL + "Bundle-ManifestVersion: 2" + NL + "Bundle-Name: Acceleo ";
+ protected final String TEXT_2 = " Module IDE Plug-in" + NL + "Bundle-SymbolicName: ";
+ protected final String TEXT_3 = ";singleton:=true" + NL + "Bundle-Version: 1.0.0.qualifier" + NL + "Bundle-Activator: ";
+ protected final String TEXT_4 = ".Activator" + NL + "Bundle-Vendor: Eclipse.org" + NL + "Require-Bundle: org.eclipse.ui," + NL + " org.eclipse.core.runtime," + NL + " org.eclipse.core.resources, ";
+ protected final String TEXT_5 = NL + " ";
+ protected final String TEXT_6 = ",";
+ protected final String TEXT_7 = NL + " org.eclipse.emf.ecore," + NL + " org.eclipse.emf.ecore.xmi," + NL + " org.eclipse.ocl," + NL + " org.eclipse.ocl.ecore," + NL + " org.eclipse.acceleo.model," + NL + " org.eclipse.acceleo.engine" + NL + "Bundle-RequiredExecutionEnvironment: J2SE-1.5" + NL + "Bundle-ActivationPolicy: lazy";
+ protected final String TEXT_8 = NL;
+
+ public String generate(Object argument)
+ {
+ final StringBuffer stringBuffer = new StringBuffer();
+
+ CreateModuleUIData content = (CreateModuleUIData) argument;
+
+ stringBuffer.append(TEXT_1);
+ stringBuffer.append(content.getModuleNameWithSpaces());
+ stringBuffer.append(TEXT_2);
+ stringBuffer.append(content.getProjectName());
+ stringBuffer.append(TEXT_3);
+ stringBuffer.append(content.getProjectName());
+ stringBuffer.append(TEXT_4);
+
+ for (int i = 0; i < content.getPluginDependencies().size(); i++) {
+ stringBuffer.append(TEXT_5);
+ stringBuffer.append(content.getPluginDependencies().get(i));
+ stringBuffer.append(TEXT_6);
+ }
+ stringBuffer.append(TEXT_7);
+ stringBuffer.append(TEXT_8);
+ return stringBuffer.toString();
+ }
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleUIPluginXMLWriter.java b/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleUIPluginXMLWriter.java
new file mode 100644
index 0000000..af3ea06
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleUIPluginXMLWriter.java
@@ -0,0 +1,49 @@
+package org.eclipse.acceleo.internal.ide.ui.wizards.newproject;
+
+public class CreateModuleUIPluginXMLWriter
+{
+ protected static String nl;
+ public static synchronized CreateModuleUIPluginXMLWriter create(String lineSeparator)
+ {
+ nl = lineSeparator;
+ CreateModuleUIPluginXMLWriter result = new CreateModuleUIPluginXMLWriter();
+ nl = null;
+ return result;
+ }
+
+ public final String NL = nl == null ? (System.getProperties().getProperty("line.separator")) : nl;
+ protected final String TEXT_1 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + NL + "<?eclipse version=\"3.2\"?>" + NL + "<plugin>" + NL + " <extension point=\"org.eclipse.ui.popupMenus\">" + NL + " <objectContribution" + NL + " adaptable=\"true\"" + NL + " objectClass=\"org.eclipse.core.resources.IFile\"" + NL + " nameFilter=\"";
+ protected final String TEXT_2 = "\"" + NL + " id=\"";
+ protected final String TEXT_3 = ".popupMenus.contribution.IFile\">" + NL + " <menu id=\"org.eclipse.acceleo.module.menu\" label=\"Model to Text Transformation\" path=\"additionsAcceleo\">" + NL + " <groupMarker name=\"acceleo\"/> " + NL + " </menu>" + NL + " <action" + NL + " class=\"";
+ protected final String TEXT_4 = ".popupMenus.AcceleoGenerate";
+ protected final String TEXT_5 = "Action\"" + NL + " enablesFor=\"+\"" + NL + " id=\"";
+ protected final String TEXT_6 = ".popupMenus.acceleoGenerate";
+ protected final String TEXT_7 = "Action\"" + NL + " icon=\"icons/default.gif\"" + NL + " label=\"Generate ";
+ protected final String TEXT_8 = "\"" + NL + " menubarPath=\"org.eclipse.acceleo.module.menu/acceleo\"/>" + NL + " </objectContribution>" + NL + " </extension>" + NL + "</plugin>";
+ protected final String TEXT_9 = NL;
+
+ public String generate(Object argument)
+ {
+ final StringBuffer stringBuffer = new StringBuffer();
+
+ CreateModuleUIData content = (CreateModuleUIData) argument;
+
+ stringBuffer.append(TEXT_1);
+ stringBuffer.append(content.getModelNameFilter());
+ stringBuffer.append(TEXT_2);
+ stringBuffer.append(content.getProjectName());
+ stringBuffer.append(TEXT_3);
+ stringBuffer.append(content.getProjectName());
+ stringBuffer.append(TEXT_4);
+ stringBuffer.append(content.getModuleNameWithoutSpaces());
+ stringBuffer.append(TEXT_5);
+ stringBuffer.append(content.getProjectName());
+ stringBuffer.append(TEXT_6);
+ stringBuffer.append(content.getModuleNameWithoutSpaces());
+ stringBuffer.append(TEXT_7);
+ stringBuffer.append(content.getModuleNameWithSpaces());
+ stringBuffer.append(TEXT_8);
+ stringBuffer.append(TEXT_9);
+ return stringBuffer.toString();
+ }
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleUIPopupMenuActionWriter.java b/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleUIPopupMenuActionWriter.java
new file mode 100644
index 0000000..c1a2134
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleUIPopupMenuActionWriter.java
@@ -0,0 +1,44 @@
+package org.eclipse.acceleo.internal.ide.ui.wizards.newproject;
+
+public class CreateModuleUIPopupMenuActionWriter
+{
+ protected static String nl;
+ public static synchronized CreateModuleUIPopupMenuActionWriter create(String lineSeparator)
+ {
+ nl = lineSeparator;
+ CreateModuleUIPopupMenuActionWriter result = new CreateModuleUIPopupMenuActionWriter();
+ nl = null;
+ return result;
+ }
+
+ public final String NL = nl == null ? (System.getProperties().getProperty("line.separator")) : nl;
+ protected final String TEXT_1 = "/*******************************************************************************" + NL + " * Copyright (c) 2008, 2009 Obeo." + NL + " * All rights reserved. This program and the accompanying materials" + NL + " * are made available under the terms of the Eclipse Public License v1.0" + NL + " * which accompanies this distribution, and is available at" + NL + " * http://www.eclipse.org/legal/epl-v10.html" + NL + " * " + NL + " * Contributors:" + NL + " * Obeo - initial API and implementation" + NL + " *******************************************************************************/" + NL + "package ";
+ protected final String TEXT_2 = ".popupMenus;" + NL + "" + NL + "import java.io.IOException;" + NL + "import java.lang.reflect.InvocationTargetException;" + NL + "import java.util.Iterator;" + NL + "import java.util.List;" + NL + "import java.util.ArrayList;" + NL + "" + NL + "import org.eclipse.core.resources.IFile;" + NL + "import org.eclipse.core.resources.IContainer;" + NL + "import org.eclipse.core.resources.IResource;" + NL + "import org.eclipse.core.runtime.CoreException;" + NL + "import org.eclipse.core.runtime.IProgressMonitor;" + NL + "import org.eclipse.core.runtime.IStatus;" + NL + "import org.eclipse.core.runtime.Status;" + NL + "import org.eclipse.emf.common.util.URI;" + NL + "import org.eclipse.jface.action.IAction;" + NL + "import org.eclipse.jface.operation.IRunnableWithProgress;" + NL + "import org.eclipse.jface.viewers.ISelection;" + NL + "import org.eclipse.jface.viewers.IStructuredSelection;" + NL + "import ";
+ protected final String TEXT_3 = ".Activator;" + NL + "import ";
+ protected final String TEXT_4 = ".common.GenerateAll;" + NL + "import org.eclipse.ui.IActionDelegate;" + NL + "import org.eclipse.ui.PlatformUI;" + NL + "import org.eclipse.ui.actions.ActionDelegate;" + NL + "" + NL + "/**" + NL + " * ";
+ protected final String TEXT_5 = " code generation." + NL + " * " + NL + " * @author <a href=\"mailto:jonathan.musset@obeo.fr\">Jonathan Musset</a>" + NL + " * " + NL + " */" + NL + "public class AcceleoGenerate";
+ protected final String TEXT_6 = "Action extends ActionDelegate implements IActionDelegate {" + NL + "\t" + NL + "\t/**" + NL + "\t * Selected model files." + NL + "\t */" + NL + "\tprotected List<IFile> files;" + NL + "" + NL + "\t/**{@inheritDoc}" + NL + "\t *" + NL + "\t * @see org.eclipse.ui.actions.ActionDelegate#selectionChanged(org.eclipse.jface.action.IAction, org.eclipse.jface.viewers.ISelection)" + NL + "\t * @generated" + NL + "\t */" + NL + "\t@SuppressWarnings(\"unchecked\")" + NL + "\tpublic void selectionChanged(IAction action, ISelection selection) {" + NL + "\t\tif (selection instanceof IStructuredSelection) {" + NL + "\t\t\tfiles = ((IStructuredSelection) selection).toList();" + NL + "\t\t}" + NL + "\t}" + NL + "" + NL + "\t/**{@inheritDoc}" + NL + "\t *" + NL + "\t * @see org.eclipse.ui.actions.ActionDelegate#run(org.eclipse.jface.action.IAction)" + NL + "\t * @generated" + NL + "\t */" + NL + "\tpublic void run(IAction action) {" + NL + "\t\tif (files != null) {" + NL + "\t\t\tIRunnableWithProgress operation = new IRunnableWithProgress() {" + NL + "\t\t\t\tpublic void run(IProgressMonitor monitor) {" + NL + "\t\t\t\t\ttry {" + NL + "\t\t\t\t\t\tIterator<IFile> filesIt = files.iterator();" + NL + "\t\t\t\t\t\twhile (filesIt.hasNext()) {" + NL + "\t\t\t\t\t\t\tIFile model = (IFile)filesIt.next();" + NL + "\t\t\t\t\t\t\tURI modelURI = URI.createPlatformResourceURI(model.getFullPath().toString(), true);" + NL + "\t\t\t\t\t\t\ttry {" + NL + "\t\t\t\t\t\t\t\t";
+ protected final String TEXT_7 = NL + "\t\t\t\t\t\t\t\tGenerateAll generator = new GenerateAll(modelURI, target.getLocation().toFile(), getArguments());" + NL + "\t\t\t\t\t\t\t\tgenerator.doGenerate();" + NL + "\t\t\t\t\t\t\t} catch (IOException e) {" + NL + "\t\t\t\t\t\t\t\tIStatus status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e);" + NL + "\t\t\t\t\t\t\t\tActivator.getDefault().getLog().log(status);" + NL + "\t\t\t\t\t\t\t} finally {" + NL + "\t\t\t\t\t\t\t\tmodel.getProject().refreshLocal(IResource.DEPTH_INFINITE, monitor);" + NL + "\t\t\t\t\t\t\t}" + NL + "\t\t\t\t\t\t}" + NL + "\t\t\t\t\t} catch (CoreException e) {" + NL + "\t\t\t\t\t\tIStatus status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e);" + NL + "\t\t\t\t\t\tActivator.getDefault().getLog().log(status);" + NL + "\t\t\t\t\t}" + NL + "\t\t\t\t}" + NL + "\t\t\t};" + NL + "\t\t\ttry {" + NL + "\t\t\t\tPlatformUI.getWorkbench().getProgressService().run(true, true, operation);" + NL + "\t\t\t} catch (InvocationTargetException e) {" + NL + "\t\t\t\tIStatus status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e);" + NL + "\t\t\t\tActivator.getDefault().getLog().log(status);" + NL + "\t\t\t} catch (InterruptedException e) {" + NL + "\t\t\t\tIStatus status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e);" + NL + "\t\t\t\tActivator.getDefault().getLog().log(status);" + NL + "\t\t\t}" + NL + "\t\t}" + NL + "\t}" + NL + "" + NL + "\t/**" + NL + "\t * Computes the arguments of the generator." + NL + "\t * " + NL + "\t * @return the arguments" + NL + "\t * @generated" + NL + "\t */" + NL + "\tprotected List<? extends Object> getArguments() {" + NL + "\t\treturn new ArrayList<String>();" + NL + "\t}" + NL + "" + NL + "}";
+
+ public String generate(Object argument)
+ {
+ final StringBuffer stringBuffer = new StringBuffer();
+
+ CreateModuleUIData content = (CreateModuleUIData) argument;
+
+ stringBuffer.append(TEXT_1);
+ stringBuffer.append(content.getProjectName());
+ stringBuffer.append(TEXT_2);
+ stringBuffer.append(content.getProjectName());
+ stringBuffer.append(TEXT_3);
+ stringBuffer.append(content.getProjectName());
+ stringBuffer.append(TEXT_4);
+ stringBuffer.append(content.getModuleNameWithSpaces());
+ stringBuffer.append(TEXT_5);
+ stringBuffer.append(content.getModuleNameWithoutSpaces());
+ stringBuffer.append(TEXT_6);
+ stringBuffer.append(content.getTargetFolderAccess().replaceAll("\n", "\n\t\t\t\t\t\t\t\t"));
+ stringBuffer.append(TEXT_7);
+ return stringBuffer.toString();
+ }
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleUIProjectWriter.java b/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleUIProjectWriter.java
new file mode 100644
index 0000000..de96946
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleUIProjectWriter.java
@@ -0,0 +1,31 @@
+package org.eclipse.acceleo.internal.ide.ui.wizards.newproject;
+
+public class CreateModuleUIProjectWriter
+{
+ protected static String nl;
+ public static synchronized CreateModuleUIProjectWriter create(String lineSeparator)
+ {
+ nl = lineSeparator;
+ CreateModuleUIProjectWriter result = new CreateModuleUIProjectWriter();
+ nl = null;
+ return result;
+ }
+
+ public final String NL = nl == null ? (System.getProperties().getProperty("line.separator")) : nl;
+ protected final String TEXT_1 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + NL + "<projectDescription>" + NL + "\t<name>";
+ protected final String TEXT_2 = "</name>" + NL + "\t<comment></comment>" + NL + "\t<projects>" + NL + "\t</projects>" + NL + "\t<buildSpec>" + NL + "\t\t<buildCommand>" + NL + "\t\t\t<name>org.eclipse.jdt.core.javabuilder</name>" + NL + "\t\t\t<arguments>" + NL + "\t\t\t</arguments>" + NL + "\t\t</buildCommand>" + NL + "\t\t<buildCommand>" + NL + "\t\t\t<name>org.eclipse.pde.ManifestBuilder</name>" + NL + "\t\t\t<arguments>" + NL + "\t\t\t</arguments>" + NL + "\t\t</buildCommand>" + NL + "\t\t<buildCommand>" + NL + "\t\t\t<name>org.eclipse.pde.SchemaBuilder</name>" + NL + "\t\t\t<arguments>" + NL + "\t\t\t</arguments>" + NL + "\t\t</buildCommand>" + NL + "\t</buildSpec>" + NL + "\t<natures>" + NL + "\t\t<nature>org.eclipse.pde.PluginNature</nature>" + NL + "\t\t<nature>org.eclipse.jdt.core.javanature</nature>" + NL + "\t</natures>" + NL + "</projectDescription>";
+ protected final String TEXT_3 = NL;
+
+ public String generate(Object argument)
+ {
+ final StringBuffer stringBuffer = new StringBuffer();
+
+ CreateModuleUIData content = (CreateModuleUIData) argument;
+
+ stringBuffer.append(TEXT_1);
+ stringBuffer.append(content.getProjectName());
+ stringBuffer.append(TEXT_2);
+ stringBuffer.append(TEXT_3);
+ return stringBuffer.toString();
+ }
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleUISettingsWriter.java b/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleUISettingsWriter.java
new file mode 100644
index 0000000..3d98cd1
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src-gen/org/eclipse/acceleo/internal/ide/ui/wizards/newproject/CreateModuleUISettingsWriter.java
@@ -0,0 +1,25 @@
+package org.eclipse.acceleo.internal.ide.ui.wizards.newproject;
+
+public class CreateModuleUISettingsWriter
+{
+ protected static String nl;
+ public static synchronized CreateModuleUISettingsWriter create(String lineSeparator)
+ {
+ nl = lineSeparator;
+ CreateModuleUISettingsWriter result = new CreateModuleUISettingsWriter();
+ nl = null;
+ return result;
+ }
+
+ public final String NL = nl == null ? (System.getProperties().getProperty("line.separator")) : nl;
+ protected final String TEXT_1 = "eclipse.preferences.version=1" + NL + "org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5" + NL + "org.eclipse.jdt.core.compiler.compliance=1.5" + NL + "org.eclipse.jdt.core.compiler.problem.assertIdentifier=error" + NL + "org.eclipse.jdt.core.compiler.problem.enumIdentifier=error" + NL + "org.eclipse.jdt.core.compiler.source=1.5";
+ protected final String TEXT_2 = NL;
+
+ public String generate(Object argument)
+ {
+ final StringBuffer stringBuffer = new StringBuffer();
+ stringBuffer.append(TEXT_1);
+ stringBuffer.append(TEXT_2);
+ return stringBuffer.toString();
+ }
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/ide/ui/AcceleoUIActivator.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/ide/ui/AcceleoUIActivator.java
new file mode 100644
index 0000000..4366d10
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/ide/ui/AcceleoUIActivator.java
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.ide.ui;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class AcceleoUIActivator extends AbstractUIPlugin {
+
+ /**
+ * The plug-in ID.
+ */
+ public static final String PLUGIN_ID = "org.eclipse.acceleo.ide.ui"; //$NON-NLS-1$
+
+ /**
+ * The shared instance.
+ */
+ private static AcceleoUIActivator plugin;
+
+ /**
+ * The images.
+ */
+ private Map<String, Image> imageMap = new HashMap<String, Image>();
+
+ /**
+ * The constructor.
+ */
+ public AcceleoUIActivator() {
+ // Default constructor
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
+ */
+ @Override
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ plugin = this;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+ */
+ @Override
+ public void stop(BundleContext context) throws Exception {
+ plugin = null;
+ super.stop(context);
+ Iterator<Image> imageIterator = imageMap.values().iterator();
+ while (imageIterator.hasNext()) {
+ Image image = imageIterator.next();
+ image.dispose();
+ }
+ imageMap.clear();
+ }
+
+ /**
+ * Returns the shared instance.
+ *
+ * @return the shared instance
+ */
+ public static AcceleoUIActivator getDefault() {
+ return plugin;
+ }
+
+ /**
+ * Returns an image at the given plug-in relative path.
+ *
+ * @param path
+ * is a plug-in relative path
+ * @return the image
+ */
+ public Image getImage(String path) {
+ Image result = imageMap.get(path);
+ if (result == null) {
+ result = getImageDescriptor(path).createImage();
+ imageMap.put(path, result);
+ }
+ return result;
+ }
+
+ /**
+ * Returns an image descriptor for the image file at the given plug-in relative path.
+ *
+ * @param path
+ * the path
+ * @return the image descriptor
+ */
+ public static ImageDescriptor getImageDescriptor(String path) {
+ return imageDescriptorFromPlugin(PLUGIN_ID, path);
+ }
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/ide/ui/launching/strategy/AcceleoPluginLaunchingStrategy.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/ide/ui/launching/strategy/AcceleoPluginLaunchingStrategy.java
new file mode 100644
index 0000000..35aa02e
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/ide/ui/launching/strategy/AcceleoPluginLaunchingStrategy.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.ide.ui.launching.strategy;
+
+import java.io.File;
+import java.util.List;
+
+import org.eclipse.acceleo.engine.service.AcceleoService;
+import org.eclipse.acceleo.model.mtl.Module;
+import org.eclipse.emf.ecore.EObject;
+
+/**
+ * Default Acceleo Plug-in launching strategy. It is used to launch an Acceleo application in the current Eclipse
+ * thread.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class AcceleoPluginLaunchingStrategy implements IAcceleoLaunchingStrategy {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.acceleo.ide.ui.launching.strategy.IAcceleoLaunchingStrategy#doGenerate(org.eclipse.acceleo.model.mtl.Module,
+ * java.util.List, org.eclipse.emf.ecore.EObject, java.util.List, java.io.File)
+ */
+ public void doGenerate(Module module, List<String> templateNames, EObject model,
+ List<? extends Object> arguments, File generationRoot) {
+ for (int i = 0; i < templateNames.size(); i++) {
+ AcceleoService.doGenerate(module, templateNames.get(i), model, arguments, generationRoot, false);
+ }
+ }
+
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/ide/ui/launching/strategy/IAcceleoLaunchingStrategy.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/ide/ui/launching/strategy/IAcceleoLaunchingStrategy.java
new file mode 100644
index 0000000..7c3c5fc
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/ide/ui/launching/strategy/IAcceleoLaunchingStrategy.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.ide.ui.launching.strategy;
+
+import java.io.File;
+import java.util.List;
+
+import org.eclipse.acceleo.model.mtl.Module;
+import org.eclipse.emf.ecore.EObject;
+
+/**
+ * An internal extension point is defined to specify multiple launching strategies. It is used to define a
+ * specific way of launching an Acceleo generation. The extension point "org.eclipse.acceleo.ide.ui.launching"
+ * requires a fully qualified name of a Java class implementing this interface.
+ *
+ * @see AcceleoPluginLaunchingStrategy
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public interface IAcceleoLaunchingStrategy {
+
+ /**
+ * The identifier of the internal extension point specifying the implementation to use for launching
+ * strategy. It is used to define a specific way of launching an Acceleo generation.
+ */
+ String LAUNCHING_STRATEGY_EXTENSION_ID = "org.eclipse.acceleo.ide.ui.launching"; //$NON-NLS-1$
+
+ /**
+ * Launches the generation for a list of Acceleo templates.
+ *
+ * @param module
+ * the module
+ * @param templateNames
+ * names of the module templates that are to be generated
+ * @param model
+ * input model for these Acceleo templates
+ * @param arguments
+ * arguments of the template call
+ * @param generationRoot
+ * this will be used as the root for the generated files. This can be <code>null</code>, in
+ * which case the user home directory should be used as root.
+ */
+ void doGenerate(Module module, List<String> templateNames, EObject model,
+ List<? extends Object> arguments, File generationRoot);
+
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/ide/ui/natures/AcceleoNature.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/ide/ui/natures/AcceleoNature.java
new file mode 100644
index 0000000..1ba0b71
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/ide/ui/natures/AcceleoNature.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.ide.ui.natures;
+
+import org.eclipse.acceleo.internal.ide.ui.builders.AcceleoBuilder;
+import org.eclipse.core.resources.ICommand;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+import org.eclipse.core.resources.IProjectNature;
+import org.eclipse.core.runtime.CoreException;
+
+/**
+ * The Acceleo nature.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class AcceleoNature implements IProjectNature {
+
+ /**
+ * ID of this project nature.
+ */
+ public static final String NATURE_ID = "org.eclipse.acceleo.ide.ui.acceleoNature"; //$NON-NLS-1$
+
+ /**
+ * The project.
+ */
+ private IProject project;
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.core.resources.IProjectNature#configure()
+ */
+ public void configure() throws CoreException {
+ IProjectDescription desc = project.getDescription();
+ ICommand[] commands = desc.getBuildSpec();
+ for (int i = 0; i < commands.length; ++i) {
+ if (commands[i].getBuilderName().equals(AcceleoBuilder.BUILDER_ID)) {
+ return;
+ }
+ }
+ ICommand[] newCommands = new ICommand[commands.length + 1];
+ System.arraycopy(commands, 0, newCommands, 0, commands.length);
+ ICommand command = desc.newCommand();
+ command.setBuilderName(AcceleoBuilder.BUILDER_ID);
+ newCommands[newCommands.length - 1] = command;
+ desc.setBuildSpec(newCommands);
+ project.setDescription(desc, null);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.core.resources.IProjectNature#deconfigure()
+ */
+ public void deconfigure() throws CoreException {
+ IProjectDescription description = getProject().getDescription();
+ ICommand[] commands = description.getBuildSpec();
+ for (int i = 0; i < commands.length; ++i) {
+ if (commands[i].getBuilderName().equals(AcceleoBuilder.BUILDER_ID)) {
+ ICommand[] newCommands = new ICommand[commands.length - 1];
+ System.arraycopy(commands, 0, newCommands, 0, i);
+ System.arraycopy(commands, i + 1, newCommands, i, commands.length - i - 1);
+ description.setBuildSpec(newCommands);
+ return;
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.core.resources.IProjectNature#getProject()
+ */
+ public IProject getProject() {
+ return project;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.core.resources.IProjectNature#setProject(org.eclipse.core.resources.IProject)
+ */
+ public void setProject(IProject project) {
+ this.project = project;
+ }
+
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/ide/ui/resources/AcceleoProject.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/ide/ui/resources/AcceleoProject.java
new file mode 100644
index 0000000..3274dee
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/ide/ui/resources/AcceleoProject.java
@@ -0,0 +1,519 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.ide.ui.resources;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.acceleo.common.IAcceleoConstants;
+import org.eclipse.acceleo.common.utils.ModelUtils;
+import org.eclipse.acceleo.ide.ui.AcceleoUIActivator;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.osgi.service.resolver.BundleDescription;
+import org.eclipse.pde.core.plugin.IPluginModelBase;
+import org.eclipse.pde.core.plugin.PluginRegistry;
+import org.osgi.framework.Bundle;
+
+/**
+ * A Acceleo project represents a view of a project resource in terms of Acceleo elements. Each Acceleo project has a
+ * classpath, defining which folders contain source code and where templates are located. Each Acceleo project
+ * also has an output location. The extension of a template is '.acceleo' and the extension of an output file is
+ * '.emtl'.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class AcceleoProject {
+
+ /**
+ * The project.
+ */
+ private IProject project;
+
+ /**
+ * The folders that contain the Acceleo sources (A Acceleo source folder is a Java source folder).
+ */
+ private List<IPath> sourceFolders;
+
+ /**
+ * Output file cache for MANIFEST.MF dependencies.
+ */
+ private List<URI> outputFilesWithManifest;
+
+ /**
+ * The MANIFEST.MF file modification stamp. If the modification stamp doesn't change, we haven't to
+ * compute the MANIFEST.MF dependencies. We can use the variable 'outputFilesWithManifest' to get the
+ * dependencies while the MANIFEST.MF file doesn't change.
+ */
+ private long manifestModificationStamp = -1;
+
+ /**
+ * Constructor.
+ *
+ * @param project
+ * is the project
+ */
+ public AcceleoProject(IProject project) {
+ this.project = project;
+ this.sourceFolders = new ArrayList<IPath>();
+ final IJavaProject javaProject = JavaCore.create(project);
+ IClasspathEntry[] entries;
+ try {
+ entries = javaProject.getResolvedClasspath(true);
+ } catch (JavaModelException e1) {
+ entries = new IClasspathEntry[] {};
+ }
+ for (int i = 0; i < entries.length; i++) {
+ IClasspathEntry entry = entries[i];
+ if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
+ this.sourceFolders.add(entry.getPath());
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals(Object obj) {
+ if (obj instanceof AcceleoProject) {
+ return ((AcceleoProject)obj).project.equals(project);
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ public int hashCode() {
+ return project.getName().hashCode();
+ }
+
+ /**
+ * Returns a list of existing Acceleo files (Acceleo files only) in this resource.
+ *
+ * @return all the Acceleo files
+ * @throws CoreException
+ * contains a status object describing the cause of the exception
+ */
+ public List<IFile> getInputFiles() throws CoreException {
+ List<IFile> filesInput = new ArrayList<IFile>();
+ for (Iterator<IPath> itSourceFolders = sourceFolders.iterator(); itSourceFolders.hasNext();) {
+ IPath sourceFolderPath = itSourceFolders.next();
+ if (sourceFolderPath.segmentCount() > 1) {
+ IFolder sourceFolder = ResourcesPlugin.getWorkspace().getRoot().getFolder(sourceFolderPath);
+ if (sourceFolder != null && sourceFolder.isAccessible()) {
+ computeInputFiles(filesInput, sourceFolder);
+ }
+ }
+ }
+ return filesInput;
+ }
+
+ /**
+ * Computes a list of existing Acceleo files (Acceleo files only) in this resource.
+ *
+ * @param filesInput
+ * an output parameter to get all the Acceleo files
+ * @param container
+ * is the container to browse
+ * @throws CoreException
+ * contains a status object describing the cause of the exception
+ */
+ private void computeInputFiles(List<IFile> filesInput, IContainer container) throws CoreException {
+ if (container != null) {
+ IResource[] children = container.members();
+ if (children != null) {
+ for (int i = 0; i < children.length; ++i) {
+ IResource resource = children[i];
+ if (resource instanceof IFile
+ && IAcceleoConstants.MTL_FILE_EXTENSION.equals(((IFile)resource).getFileExtension())) {
+ filesInput.add((IFile)resource);
+ } else if (resource instanceof IContainer) {
+ computeInputFiles(filesInput, (IContainer)resource);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Gets the output file path (EMTL) for the given Acceleo file. For example : <br>
+ * '/MyProject/src/org/eclipse/acceleo/file.acceleo' becomes '/MyProject/bin/org/eclipse/acceleo/file.emtl' </br>
+ *
+ * @param fileAcceleo
+ * is the Acceleo file
+ * @return the output file path
+ */
+ public IPath getOutputFilePath(IFile fileAcceleo) {
+ IPath filePath = fileAcceleo.getFullPath();
+ IFolder folder = getOutputFolder(project);
+ if (folder != null) {
+ for (Iterator<IPath> itSourceFolders = sourceFolders.iterator(); itSourceFolders.hasNext();) {
+ IPath sourcePath = itSourceFolders.next();
+ if (sourcePath.isPrefixOf(filePath)) {
+ IPath relativePath = filePath.removeFirstSegments(sourcePath.segmentCount());
+ return folder.getFullPath().append(
+ relativePath.removeFileExtension().addFileExtension(
+ IAcceleoConstants.EMTL_FILE_EXTENSION));
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Gets the input file path (Acceleo) for the given EMTL file path. For example : <br>
+ * '/MyProject/bin/org/eclipse/acceleo/file.emtl' becomes '/MyProject/src-gen/org/eclipse/acceleo/file.acceleo' </br>
+ *
+ * @param fileEMTL
+ * is the EMTL file path
+ * @return the input file, or null if the given file isn't valid
+ */
+ public IPath getInputFilePath(IPath fileEMTL) {
+ IFolder folder = getOutputFolder(project);
+ if (folder != null && folder.getFullPath().isPrefixOf(fileEMTL)) {
+ IPath relativePath = fileEMTL.removeFileExtension().addFileExtension(
+ IAcceleoConstants.MTL_FILE_EXTENSION)
+ .removeFirstSegments(folder.getFullPath().segmentCount());
+ for (Iterator<IPath> itSourceFolders = sourceFolders.iterator(); itSourceFolders.hasNext();) {
+ IPath sourcePath = itSourceFolders.next().append(relativePath);
+ if (ResourcesPlugin.getWorkspace().getRoot().exists(sourcePath)) {
+ return sourcePath;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * This is a helper method returning the resolved classpath for the project as a list of simple classpath
+ * entries.
+ *
+ * @return the classpath entries
+ */
+ public List<IPath> getResolvedClasspath() {
+ List<IPath> result = new ArrayList<IPath>();
+ final IJavaProject javaProject = JavaCore.create(project);
+ IClasspathEntry[] entries;
+ try {
+ entries = javaProject.getResolvedClasspath(true);
+ } catch (JavaModelException e1) {
+ entries = new IClasspathEntry[] {};
+ }
+ for (int i = 0; i < entries.length; i++) {
+ IClasspathEntry entry = entries[i];
+ result.add(entry.getPath());
+ }
+ return result;
+ }
+
+ /**
+ * Gets the full name of the package which contains the Acceleo file. For example : <br>
+ * '/MyProject/src/org/eclipse/acceleo/file.acceleo' becomes 'org.eclipse.acceleo' </br>
+ *
+ * @param fileAcceleo
+ * is the Acceleo file
+ * @return the full name of the package, or an empty string if the file is not valid
+ */
+ public String getPackageName(IFile fileAcceleo) {
+ IPath filePath = fileAcceleo.getFullPath();
+ for (Iterator<IPath> itSourceFolders = sourceFolders.iterator(); itSourceFolders.hasNext();) {
+ IPath sourcePath = itSourceFolders.next();
+ if (sourcePath.isPrefixOf(filePath)) {
+ StringBuffer name = new StringBuffer();
+ String[] segments = filePath.removeFirstSegments(sourcePath.segmentCount())
+ .removeLastSegments(1).segments();
+ for (int i = 0; i < segments.length; i++) {
+ if (i > 0) {
+ name.append("."); //$NON-NLS-1$
+ }
+ name.append(segments[i]);
+ }
+ return name.toString();
+ }
+ }
+ return ""; //$NON-NLS-1$
+ }
+
+ /**
+ * Gets the output folder of the project. For example : '/MyProject/bin'.
+ *
+ * @param aProject
+ * is a project of the workspace
+ * @return the output folder of the project, or null if it doesn't exist
+ */
+ private IFolder getOutputFolder(IProject aProject) {
+ final IJavaProject javaProject = JavaCore.create(aProject);
+ try {
+ IPath output = javaProject.getOutputLocation();
+ if (output != null && output.segmentCount() > 1) {
+ IFolder folder = aProject.getWorkspace().getRoot().getFolder(output);
+ if (folder.isAccessible()) {
+ return folder;
+ }
+ }
+ } catch (JavaModelException e) {
+ // continue
+ }
+ return null;
+ }
+
+ /**
+ * Gets all the output files (EMTL) of this project. It means the files of the project and not the files
+ * of the required plugins.
+ *
+ * @return the URIs of the output files, there are only 'workspace' URIs...
+ */
+ public List<URI> getOutputFiles() {
+ List<URI> outputURIs = new ArrayList<URI>();
+ computeAccessibleOutputFilesInFolder(outputURIs, getOutputFolder(project));
+ return outputURIs;
+ }
+
+ /**
+ * Gets all the accessible output files (EMTL) of this project. It means the files of the project and the
+ * files of the required plugins.
+ *
+ * @return the URIs of the output files, there are 'plugin' URIs and 'workspace' URIs...
+ */
+ public List<URI> getAccessibleOutputFiles() {
+ List<URI> outputURIs = new ArrayList<URI>();
+ computeAccessibleOutputFilesInFolder(outputURIs, getOutputFolder(project));
+ computeAccessibleOutputFilesWithPluginXML(outputURIs, project);
+ computeAccessibleOutputFilesWithProjectDependencies(outputURIs, project);
+ return outputURIs;
+ }
+
+ /**
+ * Computes the URIs of all the accessible output files (EMTL) in the given folder.
+ *
+ * @param outputURIs
+ * is an output parameter with all the URIs
+ * @param folder
+ * is the folder to browse
+ */
+ private void computeAccessibleOutputFilesInFolder(List<URI> outputURIs, IContainer folder) {
+ if (folder != null) {
+ try {
+ IResource[] members = folder.members();
+ for (int i = 0; i < members.length; i++) {
+ IResource member = members[i];
+ if (member instanceof IFile) {
+ if (IAcceleoConstants.EMTL_FILE_EXTENSION.equals(((IFile)member).getFileExtension())) {
+ outputURIs.add(URI.createPlatformResourceURI(((IFile)member).getFullPath()
+ .toString(), false));
+ }
+ } else if (member instanceof IContainer) {
+ computeAccessibleOutputFilesInFolder(outputURIs, (IContainer)member);
+ }
+ }
+ } catch (CoreException e) {
+ AcceleoUIActivator.getDefault().getLog().log(
+ new Status(IStatus.ERROR, AcceleoUIActivator.PLUGIN_ID, e.getMessage(), e));
+ }
+ }
+ }
+
+ /**
+ * Computes the URIs of all the accessible output files (EMTL) in the dependencies of the current plug-in
+ * (project). It browses all the required plug-ins declared in the 'plugin.xml' file.
+ *
+ * @param outputURIs
+ * is an output parameter with all the URIs
+ * @param aProject
+ * is the current plug-in
+ */
+ private void computeAccessibleOutputFilesWithPluginXML(List<URI> outputURIs, IProject aProject) {
+ IFile manifest = aProject.getFile(new Path("META-INF/MANIFEST.MF")); //$NON-NLS-1$
+ if (outputFilesWithManifest == null
+ || (manifest.isAccessible() && manifest.getModificationStamp() != manifestModificationStamp)) {
+ outputFilesWithManifest = new ArrayList<URI>();
+ manifestModificationStamp = manifest.getModificationStamp();
+ IPluginModelBase plugin = PluginRegistry.findModel(aProject);
+ if (plugin != null) {
+ BundleDescription[] requiredPlugins = plugin.getBundleDescription().getResolvedRequires();
+ for (int i = 0; i < requiredPlugins.length; i++) {
+ String requiredSymbolicName = requiredPlugins[i].getSymbolicName();
+ IProject requiredProject = ResourcesPlugin.getWorkspace().getRoot().getProject(
+ requiredSymbolicName);
+ if (requiredProject != null && requiredProject.isAccessible()) {
+ computeAccessibleOutputFilesInFolder(outputFilesWithManifest,
+ getOutputFolder(requiredProject));
+ } else if (Platform.getBundle(requiredSymbolicName) != null) {
+ computeAccessibleOutputFilesWithBundle(outputFilesWithManifest, Platform
+ .getBundle(requiredSymbolicName));
+ }
+ }
+ }
+ }
+ outputURIs.addAll(outputFilesWithManifest);
+ }
+
+ /**
+ * Computes the URIs of all the accessible output files (EMTL) in the given bundle. The bundle represents
+ * a plug-in. It browses all the entries of the bundle, to get the '.emtl' files.
+ *
+ * @param outputURIs
+ * is an output parameter with all the URIs
+ * @param bundle
+ * is the current bundle
+ */
+ @SuppressWarnings("unchecked")
+ private void computeAccessibleOutputFilesWithBundle(List<URI> outputURIs, Bundle bundle) {
+ Enumeration<URL> entries = bundle.findEntries("/", "*." + IAcceleoConstants.EMTL_FILE_EXTENSION, true); //$NON-NLS-1$ //$NON-NLS-2$
+ if (entries != null) {
+ while (entries.hasMoreElements()) {
+ URL entry = entries.nextElement();
+ if (entry != null) {
+ IPath path = new Path(entry.getPath());
+ if (path.segmentCount() > 0) {
+ outputURIs.add(URI.createPlatformPluginURI(path.toString(), false));
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Computes the URIs of all the accessible output files (EMTL) in the dependencies of the current project.
+ * It browses the resolved classpath of the java project, and keeps each entry of type
+ * 'IClasspathEntry.CPE_PROJECT'.
+ *
+ * @param outputURIs
+ * is an output parameter with all the URIs
+ * @param aProject
+ * is the current project
+ */
+ private void computeAccessibleOutputFilesWithProjectDependencies(List<URI> outputURIs, IProject aProject) {
+ final IJavaProject javaProject = JavaCore.create(aProject);
+ IClasspathEntry[] entries;
+ try {
+ entries = javaProject.getResolvedClasspath(true);
+ } catch (JavaModelException e1) {
+ entries = new IClasspathEntry[] {};
+ }
+ for (int i = 0; i < entries.length; i++) {
+ IClasspathEntry entry = entries[i];
+ if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) {
+ IProject requiredProject = ResourcesPlugin.getWorkspace().getRoot().getProject(
+ entry.getPath().toString());
+ if (requiredProject != null && requiredProject.exists()) {
+ computeAccessibleOutputFilesInFolder(outputURIs, getOutputFolder(requiredProject));
+ }
+ }
+ }
+ }
+
+ /**
+ * Gets all the accessible Acceleo projects. It means that the current project is included.
+ *
+ * @return the accessible Acceleo projects
+ */
+ public List<AcceleoProject> getRecursivelyAccessibleAcceleoProjects() {
+ List<AcceleoProject> result = new ArrayList<AcceleoProject>();
+ computeAccessibleAcceleoProjects(result, this);
+ return result;
+ }
+
+ /**
+ * Computes all the accessible Acceleo projects.
+ *
+ * @param accessibleAcceleoProjects
+ * is the output list that will contain all the accessible projects
+ * @param current
+ * is the current Acceleo project
+ */
+ private void computeAccessibleAcceleoProjects(List<AcceleoProject> accessibleAcceleoProjects, AcceleoProject current) {
+ if (!accessibleAcceleoProjects.contains(current)) {
+ accessibleAcceleoProjects.add(current);
+ IPluginModelBase plugin = PluginRegistry.findModel(current.project);
+ if (plugin != null) {
+ BundleDescription[] requiredPlugins = plugin.getBundleDescription().getResolvedRequires();
+ for (int i = 0; i < requiredPlugins.length; i++) {
+ String requiredSymbolicName = requiredPlugins[i].getSymbolicName();
+ IProject requiredProject = ResourcesPlugin.getWorkspace().getRoot().getProject(
+ requiredSymbolicName);
+ if (requiredProject != null && requiredProject.isAccessible()) {
+ AcceleoProject requiredAcceleoProject = new AcceleoProject(requiredProject);
+ computeAccessibleAcceleoProjects(accessibleAcceleoProjects, requiredAcceleoProject);
+ }
+ }
+ }
+ final IJavaProject javaProject = JavaCore.create(current.project);
+ IClasspathEntry[] entries;
+ try {
+ entries = javaProject.getResolvedClasspath(true);
+ } catch (JavaModelException e1) {
+ entries = new IClasspathEntry[] {};
+ }
+ for (int i = 0; i < entries.length; i++) {
+ IClasspathEntry entry = entries[i];
+ if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) {
+ IProject requiredProject = ResourcesPlugin.getWorkspace().getRoot().getProject(
+ entry.getPath().toString());
+ if (requiredProject != null && requiredProject.exists()) {
+ AcceleoProject requiredAcceleoProject = new AcceleoProject(requiredProject);
+ computeAccessibleAcceleoProjects(accessibleAcceleoProjects, requiredAcceleoProject);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Gets in a single resource set all the accessible AST resources (EMTL). It means the files of the
+ * project and the files of the required plugins. You must unload the resources of the returned resource
+ * set by yourself.
+ *
+ * @return a resource set which contains all the accessible resources
+ */
+ public ResourceSet loadAccessibleOutputFiles() {
+ ResourceSet oResourceSet = new ResourceSetImpl();
+ List<URI> outputURIs = getAccessibleOutputFiles();
+ for (Iterator<URI> itOutputURIs = outputURIs.iterator(); itOutputURIs.hasNext();) {
+ URI oURI = itOutputURIs.next();
+ try {
+ ModelUtils.load(oURI, oResourceSet);
+ } catch (IOException e) {
+ AcceleoUIActivator.getDefault().getLog().log(
+ new Status(IStatus.ERROR, AcceleoUIActivator.PLUGIN_ID, e.getMessage(), e));
+ }
+ }
+ return oResourceSet;
+ }
+
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/ide/ui/wizards/newfile/example/AcceleoCopyExampleContentStrategy.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/ide/ui/wizards/newfile/example/AcceleoCopyExampleContentStrategy.java
new file mode 100644
index 0000000..bc9ff82
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/ide/ui/wizards/newfile/example/AcceleoCopyExampleContentStrategy.java
@@ -0,0 +1,124 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.ide.ui.wizards.newfile.example;
+
+import org.eclipse.acceleo.internal.ide.ui.AcceleoUIMessages;
+import org.eclipse.acceleo.internal.parser.cst.utils.FileContent;
+import org.eclipse.core.resources.IFile;
+
+/**
+ * Default implementation of the "org.eclipse.acceleo.ide.ui.example" extension point. It is used to initialize
+ * automatically a template file from an example, by copying the text of the example into the new template.
+ *
+ * @see IAcceleoExampleStrategy
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class AcceleoCopyExampleContentStrategy implements IAcceleoExampleStrategy {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.acceleo.internal.ide.ui.wizards.newfile.example.IAcceleoExampleStrategy#getDescription()
+ */
+ public String getDescription() {
+ return AcceleoUIMessages.getString("AcceleoCopyExampleContentStrategy.Description"); //$NON-NLS-1$
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.acceleo.ide.ui.wizards.newfile.example.IAcceleoExampleStrategy#getInitialFileNameFilter()
+ */
+ public String getInitialFileNameFilter() {
+ return "*.java"; //$NON-NLS-1$
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.acceleo.ide.ui.wizards.newfile.example.IAcceleoExampleStrategy#forceMetamodelURI()
+ */
+ public boolean forceMetamodelURI() {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.acceleo.internal.ide.ui.wizards.newfile.example.IAcceleoExampleStrategy#getContent(org.eclipse.core.resources.IFile,
+ * java.lang.String, boolean, boolean, java.lang.String, java.lang.String)
+ */
+ public String getContent(IFile exampleFile, String moduleName, boolean templateHasFileBlock,
+ boolean templateIsMain, String metamodelURI, String metamodelFileType) {
+ String var;
+ if (metamodelFileType != null && metamodelFileType.length() > 0) {
+ var = String.valueOf(Character.toLowerCase(metamodelFileType.charAt(0)));
+ } else {
+ var = "v"; //$NON-NLS-1$
+ }
+ String fileExtension;
+ if (exampleFile != null && exampleFile.getFileExtension() != null) {
+ fileExtension = ".concat('." + exampleFile.getFileExtension() + "')"; //$NON-NLS-1$ //$NON-NLS-2$
+ } else {
+ fileExtension = ""; //$NON-NLS-1$
+ }
+ StringBuffer buffer = new StringBuffer(""); //$NON-NLS-1$
+ buffer.append("[module " + moduleName + "('" + metamodelURI + "')/]\n\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ buffer.append("[template public " + moduleName + "(" + var + " : " + metamodelFileType + ")]\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ if (templateIsMain) {
+ buffer.append("\t\n"); //$NON-NLS-1$
+ buffer.append("\t[comment @main /]\n"); //$NON-NLS-1$
+ }
+ if (templateHasFileBlock) {
+ buffer.append("\t[file (" + var + ".name" + fileExtension + ", false)]\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+ if (exampleFile != null && exampleFile.exists()) {
+ StringBuffer text = readExampleContent(exampleFile);
+ buffer.append(text);
+ } else {
+ buffer.append("\t[" + var + ".name/]\n"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ if (templateHasFileBlock) {
+ buffer.append("\t[/file]\n"); //$NON-NLS-1$
+ }
+ if (templateIsMain) {
+ buffer.append("\t\n"); //$NON-NLS-1$
+ }
+ buffer.append("[/template]\n"); //$NON-NLS-1$
+ return buffer.toString();
+ }
+
+ /**
+ * Reads the text of the example file.
+ *
+ * @param exampleFile
+ * is the example file
+ * @return the example file text
+ */
+ protected StringBuffer readExampleContent(IFile exampleFile) {
+ StringBuffer text = FileContent.getFileContent(exampleFile.getLocation().toFile());
+ char[] chars = new char[text.length()];
+ text.getChars(0, text.length(), chars, 0);
+ text = new StringBuffer();
+ for (int i = 0; i < chars.length; i++) {
+ char c = chars[i];
+ if (c == '[') {
+ text.append("['['/]"); //$NON-NLS-1$
+ } else if (c == ']') {
+ text.append("[']'/]"); //$NON-NLS-1$
+ } else {
+ text.append(c);
+ }
+ }
+ return text;
+ }
+
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/ide/ui/wizards/newfile/example/IAcceleoExampleStrategy.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/ide/ui/wizards/newfile/example/IAcceleoExampleStrategy.java
new file mode 100644
index 0000000..85af95a
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/ide/ui/wizards/newfile/example/IAcceleoExampleStrategy.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.ide.ui.wizards.newfile.example;
+
+import org.eclipse.core.resources.IFile;
+
+/**
+ * An internal extension point is defined to specify multiple example strategies. It is used to initialize
+ * automatically a template file from an example in the "New>Acceleo>Acceleo Templates" wizard. The extension point
+ * "org.eclipse.acceleo.ide.ui.example" requires a fully qualified name of a Java class implementing this
+ * interface.
+ *
+ * @see AcceleoCopyExampleContentStrategy
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public interface IAcceleoExampleStrategy {
+
+ /**
+ * The identifier of the internal extension point specifying the implementation to use for example
+ * strategy. It is used to initialize automatically a template file in the Acceleo project.
+ */
+ String EXAMPLE_STRATEGY_EXTENSION_ID = "org.eclipse.acceleo.ide.ui.example"; //$NON-NLS-1$
+
+ /**
+ * Gets the description of the strategy (Displayed in the "New>Acceleo>Acceleo Templates" wizard).
+ *
+ * @return the description of the strategy
+ */
+ String getDescription();
+
+ /**
+ * Gets the initial file name filter for this strategy.
+ *
+ * @return the initial file name filter
+ */
+ String getInitialFileNameFilter();
+
+ /**
+ * Indicates if this strategy defines itself the meta-model URI of the template to create.
+ *
+ * @return true if this strategy defines itself the meta-model URI
+ */
+ boolean forceMetamodelURI();
+
+ /**
+ * Gets the new template content, using the example file and the wizard information.
+ *
+ * @param exampleFile
+ * is the selected example
+ * @param moduleName
+ * is the module name
+ * @param templateHasFileBlock
+ * indicates if a file block must be generated
+ * @param templateIsMain
+ * indicates if a main tag (@main) must be generated
+ * @param metamodelURI
+ * is the metamodel URI
+ * @param metamodelFileType
+ * is the main metamodel type
+ * @return the new template content
+ */
+ String getContent(IFile exampleFile, String moduleName, boolean templateHasFileBlock,
+ boolean templateIsMain, String metamodelURI, String metamodelFileType);
+
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/AcceleoUIMessages.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/AcceleoUIMessages.java
new file mode 100644
index 0000000..e5a6c0b
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/AcceleoUIMessages.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2007, 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui;
+
+import java.text.MessageFormat;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+/**
+ * Utility class to access externalized Strings throughout the Acceleo user interface.
+ *
+ * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
+ */
+public final class AcceleoUIMessages {
+ /** Qualified path to the properties file in which to seek the keys. */
+ private static final String BUNDLE_NAME = "org.eclipse.acceleo.internal.ide.ui.acceleouimessages"; //$NON-NLS-1$
+
+ /** Contains the locale specific {@link String}s needed by this plug-in. */
+ private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle(BUNDLE_NAME);
+
+ /**
+ * Utility classes don't need to (and shouldn't) be instantiated.
+ */
+ private AcceleoUIMessages() {
+ // prevents instantiation
+ }
+
+ /**
+ * This will return an unformatted String from the resource bundle.
+ *
+ * @param key
+ * Key of the String we seek.
+ * @return An unformatted String from the bundle.
+ */
+ private static String internalGetString(String key) {
+ try {
+ return RESOURCE_BUNDLE.getString(key);
+ } catch (MissingResourceException e) {
+ return '!' + key + '!';
+ }
+ }
+
+ /**
+ * Returns the specified {@link String} from the resource bundle.
+ *
+ * @param key
+ * Key of the String we seek.
+ * @return The String from the resource bundle associated with <code>key</code>.
+ * <code>'!' + key + '!'</code> will be returned in case we didn't find it in the bundle.
+ */
+ public static String getString(String key) {
+ // Pass through MessageFormat so that we're consistent in the handling of special chars such as the
+ // apostrophe
+ return MessageFormat.format(internalGetString(key), new Object[] {});
+ }
+
+ /**
+ * Returns a String from the resource bundle bound with the given arguments.
+ *
+ * @param key
+ * Key of the String we seek.
+ * @param arguments
+ * Arguments for the String formatting.
+ * @return formatted {@link String}.
+ * @see MessageFormat#format(String, Object[])
+ */
+ public static String getString(String key, Object... arguments) {
+ if (arguments == null) {
+ return getString(key);
+ }
+ return MessageFormat.format(internalGetString(key), arguments);
+ }
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/acceleouimessages.properties b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/acceleouimessages.properties
new file mode 100644
index 0000000..c2f0cc6
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/acceleouimessages.properties
@@ -0,0 +1,139 @@
+################################################################################
+# Copyright (c) 2008, 2009 Obeo.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# Obeo - initial API and implementation
+################################################################################
+## note : apostrophes need to be doubled in these messages or they'll be ignored
+# org.eclipse.acceleo.internal.ide.ui.editors.template
+AcceleoElementHyperlinkDetector.OpenDeclarationLabel = Open declaration of {0}
+
+# org.eclipse.acceleo.ide.ui.builders
+AcceleoCompileOperation.Task.Compile = Acceleo Compilation
+AcceleoCompileOperation.Task.Clean = Cleaning {0}
+AcceleoCompileOperation.NameConflict = Naming conflicts in classpath for {0}
+
+# org.eclipse.acceleo.ide.ui.builders.runner
+CreateRunnableAcceleoOperation.MissingExport = The template contains a [file] block but it isn''t accessible. the package {0} must be exported via the MANIFEST file.
+CreateRunnableAcceleoOperation.MergerFailure = The Acceleo Java entries merger cannot be used on this file.
+
+# org.eclipse.acceleo.ide.ui.editors.template
+AcceleoEditor.MissingNatureTitle = Missing Acceleo Project Nature
+AcceleoEditor.MissingNatureDescription = You need to add the Acceleo Nature to this project
+
+# org.eclipse.acceleo.ide.ui.editors.template.actions
+AcceleoReferencesSearch.Result.Label = References search result
+AcceleoReferencesSearch.Result.Tooltip = References search result
+AcceleoReferencesSearch.Query.Label = References search
+
+AcceleoOutlinePageItemProvider.InvalidClassifier = Class {0} is not a valid classifier
+
+# org.eclipse.acceleo.ide.ui.wizards.newfile
+AcceleoNewTemplatesWizard.Title = Create new Acceleo templates
+AcceleoNewTemplatesWizard.MissingStrategyClass = The strategyClass attribute of extension point ''{0}'' must be specified.
+AcceleoNewTemplatesWizard.Task.CreateTemplate = Creating {0}
+AcceleoNewTemplatesWizard.Task.OpenTemplate = Opening file for edition
+
+AcceleoNewTemplateWizardPage.Name = New Acceleo Template ({0})
+AcceleoNewTemplateWizardPage.Title1 = Create a new Acceleo Template
+AcceleoNewTemplateWizardPage.TitleN = Create another Acceleo Template ({0})
+AcceleoNewTemplateWizardPage.Browse = Browse...
+AcceleoNewTemplateWizardPage.Description = This wizard creates new {0} files which can be opened in the Acceleo editor.
+AcceleoNewTemplateWizardPage.Template = Templates
+AcceleoNewTemplateWizardPage.AddButton = Add
+AcceleoNewTemplateWizardPage.RemoveButton = Remove
+AcceleoNewTemplateWizardPage.AdvanceShowedButton = Advanced >>
+AcceleoNewTemplateWizardPage.AdvanceHiddenButton = << Advanced
+AcceleoNewTemplateWizardPage.TemplateGroup = Template information
+AcceleoNewTemplateWizardPage.TemplateName = Name
+AcceleoNewTemplateWizardPage.TemplateOutput = Initialize template
+AcceleoNewTemplateWizardPage.TemplateOutputFile = File
+AcceleoNewTemplateWizardPage.TemplateExample = Select an example
+AcceleoNewTemplateWizardPage.TemplateContainer = Parent Folder
+AcceleoNewTemplateWizardPage.ContainerSelection = Select new file container
+AcceleoNewTemplateWizardPage.MetamodelGroup = Metamodel information
+AcceleoNewTemplateWizardPage.Registry = Registry
+AcceleoNewTemplateWizardPage.MetamodelURI = Metamodel URI
+AcceleoNewTemplateWizardPage.TemplateType = Generate for type
+AcceleoNewTemplateWizardPage.Error.MissingContainer = File container must be specified.
+AcceleoNewTemplateWizardPage.Error.ReadOnly = Project must be writeable.
+AcceleoNewTemplateWizardPage.Error.MissingFileName = File name must not be empty.
+AcceleoNewTemplateWizardPage.Error.InvalidFileName = File name must be valid.
+AcceleoNewTemplateWizardPage.Error.ExistingFile = File {0} already exists.
+AcceleoNewTemplateWizardPage.Error.JavaFolder = Template must be in a java source folder.
+AcceleoNewTemplateWizardPage.Error.MissingURI = Metamodel URI cannot be empty.
+AcceleoNewTemplateWizardPage.Error.InvalidURI = Metamodel URI is invalid.
+AcceleoNewTemplateWizardPage.Error.MissingType = Generation type must be specified.
+AcceleoNewTemplateWizardPage.MoreTemplates = Create more templates on next pages
+AcceleoNewTemplateWizardPage.AcceleoHasFileBlock = This template will generate a file
+AcceleoNewTemplateWizardPage.AcceleoHasMain = Create a main entry (@main)
+
+# org.eclipse.acceleo.ide.ui.wizards.newfile.example
+AcceleoCopyExampleContentStrategy.Description = Copy example content
+MTContentStrategy.Description = Migrate *.mt content
+XpandContentStrategy.Description = Migrate *.xpt content
+
+# org.eclipse.acceleo.ide.ui.wizards.newproject
+AcceleoNewProjectUIWizard.Title = Create a new Acceleo module UI project
+AcceleoNewProjectUIWizard.Module.Name = New Acceleo module UI project
+AcceleoNewProjectUIWizard.Module.Description = Select project name
+AcceleoNewProjectUIWizard.Reference.Name = Acceleo Module Selection
+AcceleoNewProjectUIWizard.Reference.Description = Select referenced modules
+AcceleoNewProjectUIWizard.Config.Name = Acceleo Module UI settings
+AcceleoNewProjectUIWizard.OverwriteProject = The project exists, you will overwrite the old files.
+
+AcceleoNewProjectWizard.Title = Create a new Acceleo module project
+AcceleoNewProjectWizard.Page.Name = New Acceleo module project
+AcceleoNewProjectWizard.Page.Description = Select project name
+
+AcceleoNewUIConfigurationPage.Title = Acceleo module UI settings
+AcceleoNewUIConfigurationPage.Description = Configuration of the popup action that will be used to run the code generation.
+AcceleoNewUIConfigurationPage.Group = Configuration
+AcceleoNewUIConfigurationPage.ModuleName = Module name
+AcceleoNewUIConfigurationPage.ModelName = Model file name filter
+AcceleoNewUIConfigurationPage.TargetFolder = Target folder access
+AcceleoNewUIConfigurationPage.Error.MissingModuleName = Module name cannot be empty.
+AcceleoNewUIConfigurationPage.Error.MissingModelName = Model name filter cannot be empty.
+AcceleoNewUIConfigurationPage.Error.MissingTargetFolder = Target folder access cannot be empty.
+
+# org.eclipse.acceleo.ide.ui.launching
+AcceleoMainTab.Error.InvalidModel = Model path isn''t valid {0}.
+AcceleoMainTab.Error.MissingModel = Model doesn''t exist {0}.
+AcceleoMainTab.Error.InvalidTarget = Target path isn''t valid {0}.
+AcceleoMainTab.Browse = Browse...
+AcceleoMainTab.ModelPath = Model:
+AcceleoMainTab.TargetPath = Target:
+AcceleoMainTab.SelectModel = Select a model
+AcceleoMainTab.Arguments = Properties:
+AcceleoMainTab.LaunchingStrategy = Runner:
+
+AcceleoMainMethodSearchEngine.SearchingForMainTypes = Searching for main types...
+
+AcceleoApplicationLaunchShortcut.Error = Error
+AcceleoApplicationLaunchShortcut.getTypeSelectionTitle = Select Acceleo Application
+AcceleoApplicationLaunchShortcut.getEditorEmptyMessage = Editor does not contain a main type (@main tag is missing in your main template)
+AcceleoApplicationLaunchShortcut.getSelectionEmptyMessage = Selection does not contain a main type (@main tag is missing in your main template)
+
+AcceleoLaunchDelegate.MissingModel = Model is missing
+AcceleoLaunchDelegate.MissingTarget = Target folder is missing
+
+AcceleoLaunchOperation.BadConfiguration = You should verify the code generation configuration because a required information is missing.
+
+#org.eclipse.acceleo.ide.ui.debug.actions
+BreakpointSelectModelRulerAction.Text = Breakpoint Condition
+BreakpointSelectModelRulerAction.DialogMessage = Put the name of the object to debug (* = any string)
+
+#org.eclipse.acceleo.ide.ui.debug.model
+AcceleoLineBreakpoint.HoverText = [{0}] {1} - line : {2}
+
+AcceleoModelPresentation.ElementText = Template Generation
+AcceleoModelPresentation.BreakpointText = {0} - line : {1}
+AcceleoModelPresentation.ProcessText = Generate
+AcceleoModelPresentation.ThreadText = Thread [main]
+AcceleoModelPresentation.TargetText = Debugging Acceleo
+
+AcceleoProcess.Label = Generate
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/builders/AcceleoBuilder.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/builders/AcceleoBuilder.java
new file mode 100644
index 0000000..1157c61
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/builders/AcceleoBuilder.java
@@ -0,0 +1,339 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.builders;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.acceleo.common.IAcceleoConstants;
+import org.eclipse.acceleo.ide.ui.resources.AcceleoProject;
+import org.eclipse.acceleo.internal.parser.cst.utils.FileContent;
+import org.eclipse.acceleo.internal.parser.cst.utils.Sequence;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IncrementalProjectBuilder;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+
+/**
+ * The builder compiles the Acceleo templates in a background task. Compilation errors are put in the problems
+ * view when it is necessary.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class AcceleoBuilder extends IncrementalProjectBuilder {
+
+ /**
+ * The builder ID.
+ */
+ public static final String BUILDER_ID = "org.eclipse.acceleo.ide.ui.acceleoBuilder"; //$NON-NLS-1$
+
+ /**
+ * The output folder to ignore.
+ */
+ private IPath outputFolder;
+
+ /**
+ * Constructor.
+ */
+ public AcceleoBuilder() {
+ super();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.core.resources.IncrementalProjectBuilder#build(int, java.util.Map,
+ * org.eclipse.core.runtime.IProgressMonitor)
+ */
+ @Override
+ @SuppressWarnings("unchecked")
+ protected IProject[] build(int kind, Map arguments, IProgressMonitor monitor) throws CoreException {
+ if (getProject() == null || !getProject().isAccessible()) {
+ return new IProject[] {};
+ } else {
+ outputFolder = getOutputFolder(getProject());
+ try {
+ if (kind == FULL_BUILD) {
+ clean(monitor);
+ fullBuild(monitor);
+ } else {
+ IResourceDelta delta = getDelta(getProject());
+ if (delta == null) {
+ clean(monitor);
+ fullBuild(monitor);
+ } else {
+ incrementalBuild(delta, monitor);
+ }
+ }
+ } catch (OperationCanceledException e) {
+ // continue
+ } finally {
+ outputFolder = null;
+ }
+ return null;
+ }
+ }
+
+ /**
+ * It does a full build.
+ *
+ * @param monitor
+ * is the progress monitor
+ * @throws CoreException
+ * contains a status object describing the cause of the exception
+ */
+ protected void fullBuild(IProgressMonitor monitor) throws CoreException {
+ List<IFile> filesOutput = new ArrayList<IFile>();
+ members(filesOutput, getProject());
+ if (filesOutput.size() > 0) {
+ IFile[] files = filesOutput.toArray(new IFile[filesOutput.size()]);
+ AcceleoCompileOperation compileOperation = new AcceleoCompileOperation(getProject(), files, false);
+ compileOperation.run(monitor);
+ }
+ }
+
+ /**
+ * It does an incremental build.
+ *
+ * @param delta
+ * is the resource delta
+ * @param monitor
+ * is the progress monitor
+ * @throws CoreException
+ * contains a status object describing the cause of the exception
+ */
+ protected void incrementalBuild(IResourceDelta delta, IProgressMonitor monitor) throws CoreException {
+ List<IFile> deltaFilesOutput = new ArrayList<IFile>();
+ deltaMembers(deltaFilesOutput, delta, monitor);
+ if (deltaFilesOutput.size() > 0) {
+ boolean containsManifest = false;
+ for (int i = 0; !containsManifest && i < deltaFilesOutput.size(); i++) {
+ containsManifest = "MANIFEST.MF".equals(deltaFilesOutput.get(i).getName()); //$NON-NLS-1$
+ }
+ if (containsManifest) {
+ deltaFilesOutput.clear();
+ members(deltaFilesOutput, getProject());
+ } else {
+ computeOtherFilesToBuild(deltaFilesOutput);
+ }
+ IFile[] files = deltaFilesOutput.toArray(new IFile[deltaFilesOutput.size()]);
+ AcceleoCompileOperation compileOperation = new AcceleoCompileOperation(getProject(), files, false);
+ compileOperation.run(monitor);
+ }
+ }
+
+ /**
+ * Gets also the files that depend of the templates to build.
+ *
+ * @param deltaFiles
+ * is an output parameter to get all the templates to build
+ * @throws CoreException
+ * contains a status object describing the cause of the exception
+ */
+ private void computeOtherFilesToBuild(List<IFile> deltaFiles) throws CoreException {
+ List<IFile> otherTemplates = new ArrayList<IFile>();
+ members(otherTemplates, getProject());
+ List<Sequence> importSequencesToSearch = new ArrayList<Sequence>();
+ for (int i = 0; i < deltaFiles.size(); i++) {
+ IFile deltaFile = deltaFiles.get(i);
+ if (IAcceleoConstants.MTL_FILE_EXTENSION.equals(deltaFile.getFileExtension())) {
+ String[] tokens = new String[] {IAcceleoConstants.DEFAULT_BEGIN, IAcceleoConstants.IMPORT,
+ new Path(deltaFile.getName()).removeFileExtension().lastSegment(),};
+ importSequencesToSearch.add(new Sequence(tokens));
+ otherTemplates.remove(deltaFile);
+ }
+ }
+ List<IFile> otherTemplatesToBuild = getOtherTemplatesToBuild(otherTemplates, importSequencesToSearch);
+ while (otherTemplatesToBuild.size() > 0) {
+ for (int i = 0; i < otherTemplatesToBuild.size(); i++) {
+ IFile otherTemplateToBuild = otherTemplatesToBuild.get(i);
+ otherTemplates.remove(otherTemplateToBuild);
+ if (!deltaFiles.contains(otherTemplateToBuild)) {
+ deltaFiles.add(otherTemplateToBuild);
+ String[] tokens = new String[] {IAcceleoConstants.DEFAULT_BEGIN, IAcceleoConstants.IMPORT,
+ new Path(otherTemplateToBuild.getName()).removeFileExtension().lastSegment(),};
+ Sequence importSequence = new Sequence(tokens);
+ importSequencesToSearch.add(importSequence);
+ }
+ }
+ otherTemplatesToBuild = getOtherTemplatesToBuild(otherTemplates, importSequencesToSearch);
+ }
+ }
+
+ /**
+ * Gets the files that import the given dependencies.
+ *
+ * @param otherTemplates
+ * are the other templates that we can decide to build
+ * @param importSequencesToSearch
+ * are the dependencies to detect in the "import" section of the other templates
+ * @return the other templates to build
+ */
+ private List<IFile> getOtherTemplatesToBuild(List<IFile> otherTemplates,
+ List<Sequence> importSequencesToSearch) {
+ AcceleoProject acceleoProject = new AcceleoProject(getProject());
+ List<IFile> result = new ArrayList<IFile>();
+ for (int i = 0; i < otherTemplates.size(); i++) {
+ IFile otherTemplate = otherTemplates.get(i);
+ IPath outputPath = acceleoProject.getOutputFilePath(otherTemplate);
+ if (outputPath != null && !getProject().getFile(outputPath.removeFirstSegments(1)).exists()) {
+ result.add(otherTemplate);
+ } else {
+ StringBuffer otherTemplateContent = FileContent.getFileContent(otherTemplate.getLocation()
+ .toFile());
+ for (int j = 0; j < importSequencesToSearch.size(); j++) {
+ Sequence importSequence = importSequencesToSearch.get(j);
+ if (importSequence.search(otherTemplateContent).b() > -1) {
+ result.add(otherTemplate);
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.core.resources.IncrementalProjectBuilder#clean(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ @Override
+ protected void clean(IProgressMonitor monitor) throws CoreException {
+ super.clean(monitor);
+ List<IFile> filesOutput = new ArrayList<IFile>();
+ members(filesOutput, getProject());
+ if (filesOutput.size() > 0) {
+ IFile[] files = filesOutput.toArray(new IFile[filesOutput.size()]);
+ AcceleoCompileOperation compileOperation = new AcceleoCompileOperation(getProject(), files, true);
+ compileOperation.run(monitor);
+ }
+ }
+
+ /**
+ * Computes a list of all the modified files (Acceleo files only).
+ *
+ * @param deltaFilesOutput
+ * an output parameter to get all the modified files
+ * @param delta
+ * the resource delta represents changes in the state of a resource tree
+ * @param monitor
+ * is the monitor
+ * @throws CoreException
+ * contains a status object describing the cause of the exception
+ */
+ private void deltaMembers(List<IFile> deltaFilesOutput, IResourceDelta delta, IProgressMonitor monitor)
+ throws CoreException {
+ if (delta != null) {
+ IResource resource = delta.getResource();
+ if (resource instanceof IFile) {
+ if (delta.getKind() == IResourceDelta.REMOVED
+ && IAcceleoConstants.MTL_FILE_EXTENSION.equals(resource.getFileExtension())) {
+ removeOutputFile((IFile)resource, monitor);
+ }
+ if (delta.getKind() != IResourceDelta.REMOVED
+ && IAcceleoConstants.MTL_FILE_EXTENSION.equals(resource.getFileExtension())) {
+ deltaFilesOutput.add((IFile)resource);
+ }
+ } else {
+ if (outputFolder == null || !outputFolder.isPrefixOf(resource.getFullPath())) {
+ IResourceDelta[] children = delta.getAffectedChildren();
+ for (int i = 0; i < children.length; i++) {
+ deltaMembers(deltaFilesOutput, children[i], monitor);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Removes the output file that corresponding to the input file.
+ *
+ * @param inputFile
+ * is the input file ('.acceleo')
+ * @param monitor
+ * is the monitor
+ * @throws CoreException
+ * contains a status object describing the cause of the exception
+ */
+ private void removeOutputFile(IFile inputFile, IProgressMonitor monitor) throws CoreException {
+ AcceleoProject acceleoProject = new AcceleoProject(getProject());
+ IPath outputPath = acceleoProject.getOutputFilePath(inputFile);
+ IResource outputFile = ResourcesPlugin.getWorkspace().getRoot().findMember(outputPath);
+ if (outputFile instanceof IFile && outputFile.isAccessible()) {
+ outputFile.delete(true, monitor);
+ }
+ }
+
+ /**
+ * Returns a list of existing member files (Acceleo files only) in this resource.
+ *
+ * @param filesOutput
+ * an output parameter to get all the Acceleo files
+ * @param container
+ * is the container to browse
+ * @throws CoreException
+ * contains a status object describing the cause of the exception
+ */
+ private void members(List<IFile> filesOutput, IContainer container) throws CoreException {
+ if (container != null) {
+ IResource[] children = container.members();
+ if (children != null) {
+ for (int i = 0; i < children.length; ++i) {
+ IResource resource = children[i];
+ if (resource instanceof IFile
+ && IAcceleoConstants.MTL_FILE_EXTENSION.equals(((IFile)resource).getFileExtension())) {
+ filesOutput.add((IFile)resource);
+ } else if (resource instanceof IContainer
+ && (outputFolder == null || !outputFolder.isPrefixOf(resource.getFullPath()))) {
+ members(filesOutput, (IContainer)resource);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Gets the output folder of the project. For example : '/MyProject/bin'.
+ *
+ * @param aProject
+ * is a project of the workspace
+ * @return the output folder of the project, or null if it doesn't exist
+ */
+ private IPath getOutputFolder(IProject aProject) {
+ final IJavaProject javaProject = JavaCore.create(aProject);
+ try {
+ IPath output = javaProject.getOutputLocation();
+ if (output != null && output.segmentCount() > 1) {
+ IFolder folder = aProject.getWorkspace().getRoot().getFolder(output);
+ if (folder.isAccessible()) {
+ return folder.getFullPath();
+ }
+ }
+ } catch (JavaModelException e) {
+ // continue
+ }
+ return null;
+ }
+
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/builders/AcceleoCompileOperation.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/builders/AcceleoCompileOperation.java
new file mode 100644
index 0000000..1cacb03
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/builders/AcceleoCompileOperation.java
@@ -0,0 +1,232 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.builders;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.acceleo.common.IAcceleoConstants;
+import org.eclipse.acceleo.ide.ui.AcceleoUIActivator;
+import org.eclipse.acceleo.ide.ui.resources.AcceleoProject;
+import org.eclipse.acceleo.internal.ide.ui.AcceleoUIMessages;
+import org.eclipse.acceleo.internal.ide.ui.builders.runner.CreateRunnableAcceleoOperation;
+import org.eclipse.acceleo.internal.parser.cst.utils.FileContent;
+import org.eclipse.acceleo.internal.parser.cst.utils.Sequence;
+import org.eclipse.acceleo.parser.AcceleoParser;
+import org.eclipse.acceleo.parser.AcceleoParserProblem;
+import org.eclipse.acceleo.parser.AcceleoParserProblems;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.emf.common.util.URI;
+
+/**
+ * The operation that compiles the templates in a background task.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class AcceleoCompileOperation implements IWorkspaceRunnable {
+
+ /**
+ * The project.
+ */
+ private IProject project;
+
+ /**
+ * The templates to compile.
+ */
+ private IFile[] files;
+
+ /**
+ * Indicates if the current purpose of the builder is to clean the project.
+ */
+ private boolean isClean;
+
+ /**
+ * Constructor.
+ *
+ * @param project
+ * is the project
+ * @param files
+ * are the templates to compile
+ * @param isClean
+ * indicates if the current purpose of the builder is to clean the project
+ * @throws CoreException
+ * contains a status object describing the cause of the exception
+ */
+ public AcceleoCompileOperation(IProject project, IFile[] files, boolean isClean) throws CoreException {
+ this.project = project;
+ this.files = files;
+ this.isClean = isClean;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.core.resources.IWorkspaceRunnable#run(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ public void run(IProgressMonitor monitor) throws CoreException {
+ monitor.beginTask(AcceleoUIMessages.getString("AcceleoCompileOperation.Task.Compile"), files.length); //$NON-NLS-1$
+ AcceleoProject acceleoProject = new AcceleoProject(project);
+ for (int i = 0; i < files.length; i++) {
+ monitor.subTask(AcceleoUIMessages.getString(
+ "AcceleoCompileOperation.Task.Clean", files[0].getFullPath().toString())); //$NON-NLS-1$
+ files[i].deleteMarkers(IMarker.PROBLEM, true, IResource.DEPTH_INFINITE);
+ IPath outputPath = acceleoProject.getOutputFilePath(files[i]);
+ if (outputPath != null) {
+ IFile outputFile = project.getFile(outputPath.removeFirstSegments(1));
+ if (outputFile != null && outputFile.exists()) {
+ outputFile.delete(true, monitor);
+ }
+ }
+ }
+ if (!isClean) {
+ doCompileResources(monitor);
+ }
+ monitor.done();
+ }
+
+ /**
+ * Compiles the templates. Creates an AST model from a list of Acceleo files, using a CST step. The
+ * dependencies are loaded before link resolution.
+ *
+ * @param monitor
+ * is the monitor
+ * @throws CoreException
+ * contains a status object describing the cause of the exception
+ */
+ private void doCompileResources(IProgressMonitor monitor) throws CoreException {
+ List<String> conflicts = new ArrayList<String>();
+ AcceleoProject acceleoProject = new AcceleoProject(project);
+ List<URI> dependenciesURIs = acceleoProject.getAccessibleOutputFiles();
+ for (Iterator<URI> iterator = dependenciesURIs.iterator(); iterator.hasNext();) {
+ URI uri = iterator.next();
+ conflicts.add(new Path(uri.toString()).removeFileExtension().addFileExtension(
+ IAcceleoConstants.MTL_FILE_EXTENSION).lastSegment());
+ }
+ AcceleoParser parser = new AcceleoParser();
+ List<File> iFiles = new ArrayList<File>();
+ List<URI> oURIs = new ArrayList<URI>();
+ for (int i = 0; i < files.length; i++) {
+ if (acceleoProject.getOutputFilePath(files[i]) != null) {
+ if (conflicts.contains(files[i].getName())) {
+ reportError(files[i], 0, 0, 0, AcceleoUIMessages.getString(
+ "AcceleoCompileOperation.NameConflict", files[i].getName())); //$NON-NLS-1$
+ } else {
+ conflicts.add(files[i].getName());
+ }
+ IPath outputPath = acceleoProject.getOutputFilePath(files[i]);
+ if (outputPath != null) {
+ iFiles.add(files[i].getLocation().toFile());
+ oURIs.add(URI.createPlatformResourceURI(outputPath.toString(), false));
+ }
+ }
+ }
+ parser.parse(iFiles, oURIs, dependenciesURIs);
+ for (Iterator<File> iterator = iFiles.iterator(); iterator.hasNext();) {
+ File iFile = iterator.next();
+ AcceleoParserProblems problems = parser.getProblems(iFile);
+ if (problems != null) {
+ IFile workspaceFile = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(
+ new Path(iFile.getAbsolutePath()));
+ if (workspaceFile != null && workspaceFile.isAccessible()) {
+ List<AcceleoParserProblem> list = problems.getList();
+ for (Iterator<AcceleoParserProblem> itProblems = list.iterator(); itProblems.hasNext();) {
+ AcceleoParserProblem problem = itProblems.next();
+ reportError(workspaceFile, problem.getLine(), problem.getPosBegin(), problem
+ .getPosEnd(), problem.getMessage());
+ }
+ }
+ }
+ }
+ List<IFile> filesWithMainTag = new ArrayList<IFile>();
+ for (Iterator<File> iterator = iFiles.iterator(); iterator.hasNext();) {
+ File iFile = iterator.next();
+ IFile workspaceFile = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(
+ new Path(iFile.getAbsolutePath()));
+ if (workspaceFile != null && workspaceFile.isAccessible() && hasMainTag(workspaceFile)) {
+ filesWithMainTag.add(workspaceFile);
+ }
+ }
+ CreateRunnableAcceleoOperation createRunnableAcceleoOperation = new CreateRunnableAcceleoOperation(acceleoProject,
+ filesWithMainTag);
+ createRunnableAcceleoOperation.run(monitor);
+ }
+
+ /**
+ * Indicates if the given file contains a main tag (@main).
+ *
+ * @param file
+ * is the template file
+ * @return true if the given file contains a main tag (@main)
+ */
+ private boolean hasMainTag(IFile file) {
+ Sequence pattern = new Sequence(IAcceleoConstants.TAG_MAIN);
+ try {
+ InputStream inputStream = file.getContents();
+ int available = inputStream.available();
+ byte[] bytes = new byte[available];
+ inputStream.read(bytes);
+ StringBuffer contents = FileContent.getFileContent(file.getLocation().toFile());
+ if (pattern.search(contents).b() > -1) {
+ return true;
+ }
+ } catch (CoreException e) {
+ AcceleoUIActivator.getDefault().getLog().log(
+ new Status(IStatus.ERROR, AcceleoUIActivator.PLUGIN_ID, e.getMessage(), e));
+ } catch (IOException e) {
+ AcceleoUIActivator.getDefault().getLog().log(
+ new Status(IStatus.ERROR, AcceleoUIActivator.PLUGIN_ID, e.getMessage(), e));
+ }
+ return false;
+ }
+
+ /**
+ * Creates an error marker on the given file.
+ *
+ * @param file
+ * is the file that contains a syntax error
+ * @param line
+ * is the line of the problem
+ * @param posBegin
+ * is the beginning position of the problem
+ * @param posEnd
+ * is the ending position of the problem
+ * @param message
+ * is the message of the problem, it is the message displayed when you're hover the marker
+ * @throws CoreException
+ * contains a status object describing the cause of the exception
+ */
+ private void reportError(IFile file, int line, int posBegin, int posEnd, String message)
+ throws CoreException {
+ IMarker m = file.createMarker(AcceleoMarker.PROBLEM_MARKER);
+ m.setAttribute(IMarker.LINE_NUMBER, line);
+ m.setAttribute(IMarker.CHAR_START, posBegin);
+ m.setAttribute(IMarker.CHAR_END, posEnd);
+ m.setAttribute(IMarker.MESSAGE, message);
+ m.setAttribute(IMarker.PRIORITY, IMarker.PRIORITY_HIGH);
+ m.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
+ }
+
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/builders/AcceleoMarker.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/builders/AcceleoMarker.java
new file mode 100644
index 0000000..fa6a05e
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/builders/AcceleoMarker.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.builders;
+
+/**
+ * Acceleo Marker.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public interface AcceleoMarker {
+
+ /**
+ * Acceleo Problem marker ID.
+ */
+ String PROBLEM_MARKER = "org.eclipse.acceleo.ide.ui.problem"; //$NON-NLS-1$
+
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/builders/runner/CreateRunnableAcceleoContent.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/builders/runner/CreateRunnableAcceleoContent.java
new file mode 100644
index 0000000..8e1466f
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/builders/runner/CreateRunnableAcceleoContent.java
@@ -0,0 +1,150 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.builders.runner;
+
+import java.util.List;
+
+/**
+ * The class used to configure the 'CreateRunnableJavaWriter' JET generation.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class CreateRunnableAcceleoContent {
+
+ /**
+ * The name of the project.
+ */
+ private String projectName;
+
+ /**
+ * The base package of the class to create.
+ */
+ private String basePackage;
+
+ /**
+ * The name of the class.
+ */
+ private String classShortName;
+
+ /**
+ * The name of the module file.
+ */
+ private String moduleFileShortName;
+
+ /**
+ * The name of the templates.
+ */
+ private List<String> templateNames;
+
+ /**
+ * The meta-models packages to consider.
+ */
+ private List<String> packages;
+
+ /**
+ * The resolved classpath for the project as a list of simple classpath entries.
+ */
+ private List<String> resolvedClasspath;
+
+ /**
+ * Constructor.
+ *
+ * @param projectName
+ * the name of the project
+ * @param basePackage
+ * the base package of the class to create
+ * @param classShortName
+ * the name of the class
+ * @param moduleFileShortName
+ * the name of the module file
+ * @param templateNames
+ * the name of the templates
+ * @param packages
+ * the meta-models packages to consider
+ * @param resolvedClasspath
+ * resolved classpath for the project as a list of simple classpath entries
+ */
+ public CreateRunnableAcceleoContent(String projectName, String basePackage, String classShortName,
+ String moduleFileShortName, List<String> templateNames, List<String> packages,
+ List<String> resolvedClasspath) {
+ super();
+ this.projectName = projectName;
+ this.basePackage = basePackage;
+ this.classShortName = classShortName;
+ this.moduleFileShortName = moduleFileShortName;
+ this.templateNames = templateNames;
+ this.packages = packages;
+ this.resolvedClasspath = resolvedClasspath;
+ }
+
+ /**
+ * Gets the name of the project.
+ *
+ * @return the name of the project
+ */
+ public String getProjectName() {
+ return projectName;
+ }
+
+ /**
+ * Gets the base package of the class to create.
+ *
+ * @return the base package of the class to create
+ */
+ public String getBasePackage() {
+ return basePackage;
+ }
+
+ /**
+ * Gets the name of the class.
+ *
+ * @return the name of the class
+ */
+ public String getClassShortName() {
+ return classShortName;
+ }
+
+ /**
+ * Gets the name of the module file.
+ *
+ * @return the name of the module file
+ */
+ public String getModuleFileShortName() {
+ return moduleFileShortName;
+ }
+
+ /**
+ * Gets the name of the templates.
+ *
+ * @return the name of the templates
+ */
+ public List<String> getTemplateNames() {
+ return templateNames;
+ }
+
+ /**
+ * Gets the meta-models packages to consider.
+ *
+ * @return the meta-models packages to consider
+ */
+ public List<String> getPackages() {
+ return packages;
+ }
+
+ /**
+ * Gets the resolved classpath for the project as a list of simple classpath entries.
+ *
+ * @return the resolved classpath for the project as a list of simple classpath entries
+ */
+ public List<String> getResolvedClasspath() {
+ return resolvedClasspath;
+ }
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/builders/runner/CreateRunnableAcceleoOperation.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/builders/runner/CreateRunnableAcceleoOperation.java
new file mode 100644
index 0000000..0f0c9e8
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/builders/runner/CreateRunnableAcceleoOperation.java
@@ -0,0 +1,350 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.builders.runner;
+
+import java.io.ByteArrayInputStream;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.acceleo.common.utils.ModelUtils;
+import org.eclipse.acceleo.ide.ui.AcceleoUIActivator;
+import org.eclipse.acceleo.ide.ui.resources.AcceleoProject;
+import org.eclipse.acceleo.internal.ide.ui.AcceleoUIMessages;
+import org.eclipse.acceleo.internal.ide.ui.builders.AcceleoMarker;
+import org.eclipse.acceleo.internal.parser.cst.utils.FileContent;
+import org.eclipse.acceleo.model.mtl.Module;
+import org.eclipse.acceleo.model.mtl.MtlPackage;
+import org.eclipse.acceleo.model.mtl.Template;
+import org.eclipse.acceleo.model.mtl.TypedModel;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.emf.codegen.merge.java.JControlModel;
+import org.eclipse.emf.codegen.merge.java.JMerger;
+import org.eclipse.emf.codegen.merge.java.facade.ast.ASTFacadeHelper;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
+
+/**
+ * The operation that compiles the FileBlock elements of the module in a background task. It creates a java
+ * file and an ANT task for each template.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class CreateRunnableAcceleoOperation implements IWorkspaceRunnable {
+
+ /**
+ * The Acceleo project which contains the templates to be considered.
+ */
+ private AcceleoProject acceleoProject;
+
+ /**
+ * A list of templates to be considered.
+ */
+ private List<IFile> files;
+
+ /**
+ * Constructor.
+ *
+ * @param acceleoProject
+ * project which contains the templates
+ * @param files
+ * are the templates to be considered
+ */
+ public CreateRunnableAcceleoOperation(AcceleoProject acceleoProject, List<IFile> files) {
+ super();
+ this.acceleoProject = acceleoProject;
+ this.files = files;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.core.resources.IWorkspaceRunnable#run(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ public void run(IProgressMonitor monitor) throws CoreException {
+ try {
+ Iterator<IFile> filesIt = files.iterator();
+ if (filesIt.hasNext()) {
+ List<String> resolvedClasspath = new ArrayList<String>();
+ Iterator<IPath> entries = acceleoProject.getResolvedClasspath().iterator();
+ IPath eclipseWorkspace = ResourcesPlugin.getWorkspace().getRoot().getLocation();
+ IPath eclipseHome = new Path(Platform.getInstallLocation().getURL().getPath());
+ while (entries.hasNext()) {
+ IPath path = entries.next();
+ if (eclipseWorkspace.isPrefixOf(path)) {
+ resolvedClasspath.add("${ECLIPSE_WORKSPACE}/" //$NON-NLS-1$
+ + path.toString().substring(eclipseWorkspace.toString().length()));
+ } else if (eclipseHome.isPrefixOf(path)) {
+ resolvedClasspath.add("${ECLIPSE_HOME}/" //$NON-NLS-1$
+ + path.toString().substring(eclipseHome.toString().length()));
+ }
+ }
+ while (filesIt.hasNext()) {
+ IFile fileAcceleo = filesIt.next();
+ String packageName = acceleoProject.getPackageName(fileAcceleo);
+ IFile manifest = fileAcceleo.getProject().getFile("/META-INF/MANIFEST.MF"); //$NON-NLS-1$
+ if (manifest.exists()
+ && FileContent.getFileContent(manifest.getLocation().toFile()).indexOf(
+ packageName) == -1) {
+ reportError(fileAcceleo, 0, 0, 0, AcceleoUIMessages.getString(
+ "CreateRunnableAcceleoOperation.MissingExport", packageName)); //$NON-NLS-1$
+ }
+ URI moduleURI = URI.createPlatformResourceURI(acceleoProject.getOutputFilePath(fileAcceleo)
+ .toString(), true);
+ ResourceSet resourceSet = new ResourceSetImpl();
+ try {
+ registerPackages(resourceSet);
+ List<String> packages = new ArrayList<String>();
+ EObject module = ModelUtils.load(moduleURI, resourceSet);
+ if (module instanceof Module) {
+ Iterator<TypedModel> typedModelIt = ((Module)module).getInput().iterator();
+ while (typedModelIt.hasNext()) {
+ Iterator<EPackage> packagesIt = typedModelIt.next().getTakesTypesFrom()
+ .iterator();
+ while (packagesIt.hasNext()) {
+ EPackage ePackage = packagesIt.next();
+ String mClass = getMetamodelPackageClass(ePackage);
+ if (mClass != null && !packages.contains(mClass)) {
+ packages.add(mClass);
+ }
+ }
+ }
+ }
+ String classShortName = new Path(Character.toUpperCase(fileAcceleo.getName().charAt(0))
+ + fileAcceleo.getName().substring(1)).removeFileExtension().lastSegment();
+ List<String> mainTemplateNames = new ArrayList<String>();
+ computesMainTemplateNames(mainTemplateNames, module);
+ if (mainTemplateNames.size() > 0) {
+ CreateRunnableAcceleoContent arg = new CreateRunnableAcceleoContent(fileAcceleo.getProject()
+ .getName(), packageName, classShortName, new Path(fileAcceleo.getName())
+ .removeFileExtension().lastSegment(), mainTemplateNames, packages,
+ resolvedClasspath);
+ CreateRunnableJavaWriter javaWriter = new CreateRunnableJavaWriter();
+ String javaText = javaWriter.generate(arg);
+ IFile javaFile = fileAcceleo.getParent().getFile(
+ new Path(classShortName).addFileExtension("java")); //$NON-NLS-1$
+ createFile(javaFile, javaText, monitor);
+ IFolder antFolder = fileAcceleo.getProject().getFolder("tasks"); //$NON-NLS-1$
+ if (antFolder.exists()) {
+ CreateRunnableAntWriter antWriter = new CreateRunnableAntWriter();
+ String antText = antWriter.generate(arg);
+ IFile antFile = antFolder.getFile(new Path(fileAcceleo.getName())
+ .removeFileExtension().addFileExtension("xml")); //$NON-NLS-1$
+ createFile(antFile, antText, monitor);
+ CreateRunnableAntCallWriter antCallWriter = new CreateRunnableAntCallWriter();
+ String antCallText = antCallWriter.generate(arg);
+ IFile antCallFile = antFolder.getFile(new Path(fileAcceleo.getName())
+ .removeFileExtension().addFileExtension("readme")); //$NON-NLS-1$
+ createFile(antCallFile, antCallText, monitor);
+ }
+ // else : We don't want to create the ANT folder if it doesn't exist
+ }
+ } finally {
+ Iterator<Resource> resources = resourceSet.getResources().iterator();
+ while (resources.hasNext()) {
+ resources.next().unload();
+ }
+ }
+ }
+ }
+ } catch (IOException e) {
+ AcceleoUIActivator.getDefault().getLog().log(
+ new Status(IStatus.ERROR, AcceleoUIActivator.PLUGIN_ID, e.getMessage(), e));
+ }
+ }
+
+ /**
+ * Updates the registry used for looking up a package based namespace, in the resource set.
+ *
+ * @param resourceSet
+ * is the resource set
+ */
+ private void registerPackages(ResourceSet resourceSet) {
+ resourceSet.getPackageRegistry().put(org.eclipse.ocl.ecore.EcorePackage.eINSTANCE.getNsURI(),
+ org.eclipse.ocl.ecore.EcorePackage.eINSTANCE);
+ resourceSet.getPackageRegistry().put(
+ org.eclipse.ocl.expressions.ExpressionsPackage.eINSTANCE.getNsURI(),
+ org.eclipse.ocl.expressions.ExpressionsPackage.eINSTANCE);
+ resourceSet.getPackageRegistry().put(MtlPackage.eINSTANCE.getNsURI(), MtlPackage.eINSTANCE);
+ }
+
+ /**
+ * Get the registered package class name to use for the classes of the given metamodel.
+ *
+ * @param metamodel
+ * is a metamodel
+ * @return the registered package class name
+ */
+ private String getMetamodelPackageClass(EPackage metamodel) {
+ // FIXME can't we simply return metamodel.getClass().getName()
+ // EPackage.Registry.INSTANCE.getEPackage(metamodel.getNsURI())
+ IExtensionRegistry registry = Platform.getExtensionRegistry();
+ IExtensionPoint extensionPoint = registry
+ .getExtensionPoint("org.eclipse.emf.ecore.generated_package"); //$NON-NLS-1$
+ if (extensionPoint != null && extensionPoint.getExtensions().length > 0) {
+ IExtension[] extensions = extensionPoint.getExtensions();
+ for (int i = 0; i < extensions.length; i++) {
+ IExtension extension = extensions[i];
+ IConfigurationElement[] members = extension.getConfigurationElements();
+ for (int j = 0; j < members.length; j++) {
+ IConfigurationElement member = members[j];
+ String mURI = member.getAttribute("uri"); //$NON-NLS-1$
+ if (mURI != null && mURI.equals(metamodel.getNsURI())) {
+ String mClass = member.getAttribute("class"); //$NON-NLS-1$
+ if (mClass != null) {
+ return mClass;
+ }
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Gets all the templates that contain the main tag (@main).
+ *
+ * @param mainTemplateNames
+ * are the templates that contain the main tag (output parameter)
+ * @param eObject
+ * is the object to browse
+ */
+ private void computesMainTemplateNames(List<String> mainTemplateNames, EObject eObject) {
+ if (eObject instanceof Template) {
+ Template eTemplate = (Template)eObject;
+ if (eTemplate.isMain() && !mainTemplateNames.contains(eTemplate.getName())) {
+ mainTemplateNames.add(eTemplate.getName());
+ }
+ } else if (eObject != null) {
+ Iterator<EObject> eContentsIt = eObject.eContents().iterator();
+ while (eContentsIt.hasNext()) {
+ EObject eContent = eContentsIt.next();
+ computesMainTemplateNames(mainTemplateNames, eContent);
+ }
+ }
+ }
+
+ /**
+ * Creates the given file and its content.
+ *
+ * @param newFile
+ * is the file to create
+ * @param content
+ * is the content of the new file
+ * @param monitor
+ * is the monitor
+ * @throws UnsupportedEncodingException
+ * when an encoding problem has been detected
+ * @throws CoreException
+ * contains a status object describing the cause of the exception
+ */
+ private void createFile(IFile newFile, String content, IProgressMonitor monitor)
+ throws UnsupportedEncodingException, CoreException {
+ IFile file = newFile;
+ String text = content;
+ if (file.exists() && "java".equals(file.getFileExtension())) { //$NON-NLS-1$
+ String jmergeFile = URI.createPlatformPluginURI(
+ "org.eclipse.emf.codegen.ecore/templates/emf-merge.xml", false).toString(); //$NON-NLS-1$
+ JControlModel model = new JControlModel();
+ ASTFacadeHelper astFacadeHelper = new ASTFacadeHelper();
+ model.initialize(astFacadeHelper, jmergeFile);
+ if (model.canMerge()) {
+ JMerger jMerger = new JMerger(model);
+ jMerger.setSourceCompilationUnit(jMerger.createCompilationUnitForContents(text));
+ try {
+ jMerger.setTargetCompilationUnit(jMerger
+ .createCompilationUnitForInputStream(new FileInputStream(file.getLocation()
+ .toFile()))); // target=last generated code
+ jMerger.merge();
+ text = jMerger.getTargetCompilationUnit().getContents();
+ } catch (FileNotFoundException e) {
+ AcceleoUIActivator.getDefault().getLog().log(
+ new Status(IStatus.ERROR, AcceleoUIActivator.PLUGIN_ID, e.getMessage(), e));
+ }
+ } else {
+ AcceleoUIActivator.getDefault().getLog().log(
+ new Status(IStatus.WARNING, AcceleoUIActivator.PLUGIN_ID, AcceleoUIMessages
+ .getString("CreateRunnableAcceleoOperation.MergerFailure"), null)); //$NON-NLS-1$
+ }
+ }
+ if (!file.exists() && file.getParent().exists()) {
+ IResource[] members = file.getParent().members(IResource.FILE);
+ for (int i = 0; i < members.length; i++) {
+ if (members[i] instanceof IFile
+ && file.getName().toLowerCase().equals(members[i].getName().toLowerCase())) {
+ file = (IFile)members[i];
+ break;
+ }
+ }
+ }
+ if (!file.exists()
+ || !text.equals(FileContent.getFileContent(file.getLocation().toFile()).toString())) {
+ ByteArrayInputStream javaStream = new ByteArrayInputStream(text.getBytes("UTF8")); //$NON-NLS-1$
+ if (!file.exists()) {
+ file.create(javaStream, true, monitor);
+ } else {
+ file.setContents(javaStream, true, false, monitor);
+ }
+ }
+ }
+
+ /**
+ * Creates an error marker on the given file.
+ *
+ * @param file
+ * is the file that contains a syntax error
+ * @param line
+ * is the line of the problem
+ * @param posBegin
+ * is the beginning position of the problem
+ * @param posEnd
+ * is the ending position of the problem
+ * @param message
+ * is the message of the problem, it is the message displayed when you're hover the marker
+ * @throws CoreException
+ * contains a status object describing the cause of the exception
+ */
+ private void reportError(IFile file, int line, int posBegin, int posEnd, String message)
+ throws CoreException {
+ IMarker m = file.createMarker(AcceleoMarker.PROBLEM_MARKER);
+ m.setAttribute(IMarker.LINE_NUMBER, line);
+ m.setAttribute(IMarker.CHAR_START, posBegin);
+ m.setAttribute(IMarker.CHAR_END, posEnd);
+ m.setAttribute(IMarker.MESSAGE, message);
+ m.setAttribute(IMarker.PRIORITY, IMarker.PRIORITY_HIGH);
+ m.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
+ }
+
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/actions/AbstractBreakpointRulerAction.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/actions/AbstractBreakpointRulerAction.java
new file mode 100644
index 0000000..0b5a6eb
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/actions/AbstractBreakpointRulerAction.java
@@ -0,0 +1,195 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.debug.actions;
+
+import org.eclipse.acceleo.ide.ui.AcceleoUIActivator;
+import org.eclipse.acceleo.internal.ide.ui.debug.model.AcceleoLineBreakpoint;
+import org.eclipse.acceleo.internal.ide.ui.debug.model.AcceleoModelPresentation;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.model.IBreakpoint;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.jface.text.source.IVerticalRulerInfo;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.texteditor.AbstractMarkerAnnotationModel;
+import org.eclipse.ui.texteditor.IDocumentProvider;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.ui.texteditor.IUpdate;
+
+/**
+ * An abstract breakpoint ruler action.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public abstract class AbstractBreakpointRulerAction extends Action implements IUpdate {
+
+ /**
+ * A vertical ruler is a visual component which may serve text viewers as an annotation presentation area.
+ */
+ protected IVerticalRulerInfo info;
+
+ /**
+ * The text editor.
+ */
+ protected ITextEditor textEditor;
+
+ /**
+ * The breakpoint.
+ */
+ private IBreakpoint breakpoint;
+
+ /**
+ * Gets the breakpoint.
+ *
+ * @return the breakpoint
+ */
+ protected IBreakpoint getBreakpoint() {
+ return breakpoint;
+ }
+
+ /**
+ * Sets the breakpoint.
+ *
+ * @param aBreakpoint
+ * is the breakpoint
+ */
+ protected void setBreakpoint(IBreakpoint aBreakpoint) {
+ breakpoint = aBreakpoint;
+ }
+
+ /**
+ * Gets the text editor.
+ *
+ * @return the text editor
+ */
+ protected ITextEditor getTextEditor() {
+ return textEditor;
+ }
+
+ /**
+ * Sets the text editor.
+ *
+ * @param aTextEditor
+ * is text editor
+ */
+ protected void setTextEditor(ITextEditor aTextEditor) {
+ textEditor = aTextEditor;
+ }
+
+ /**
+ * Gets the vertical ruler which may serve text viewers as an annotation presentation area.
+ *
+ * @return the vertical ruler
+ */
+ protected IVerticalRulerInfo getInfo() {
+ return info;
+ }
+
+ /**
+ * Sets the vertical ruler.
+ *
+ * @param rulerInfo
+ * is the vertical ruler
+ */
+ protected void setInfo(IVerticalRulerInfo rulerInfo) {
+ info = rulerInfo;
+ }
+
+ /**
+ * Returns the breakpoint.
+ *
+ * @return the breakpoint
+ */
+ protected IBreakpoint determineBreakpoint() {
+ IBreakpoint[] breakpoints = DebugPlugin.getDefault().getBreakpointManager().getBreakpoints(
+ AcceleoModelPresentation.ID_ACCELEO_DEBUG_MODEL);
+ for (int i = 0; i < breakpoints.length; i++) {
+ if (breakpoints[i] instanceof AcceleoLineBreakpoint) {
+ try {
+ if (breakpointAtRulerLine((AcceleoLineBreakpoint)breakpoints[i])) {
+ return breakpoints[i];
+ }
+ } catch (CoreException e) {
+ AcceleoUIActivator.getDefault().getLog().log(e.getStatus());
+ continue;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Indicates if the given breakpoint is active at the ruler line.
+ *
+ * @param aBreakpoint
+ * is the breakpoint
+ * @return true if the given breakpoint is active
+ * @throws CoreException
+ * when an issue occurs
+ */
+ private boolean breakpointAtRulerLine(AcceleoLineBreakpoint aBreakpoint) throws CoreException {
+ AbstractMarkerAnnotationModel model = getAnnotationModel();
+ if (model != null) {
+ Position position = model.getMarkerPosition(aBreakpoint.getMarker());
+ if (position != null) {
+ IDocumentProvider provider = getTextEditor().getDocumentProvider();
+ IDocument doc = provider.getDocument(getTextEditor().getEditorInput());
+ try {
+ int markerLineNumber = doc.getLineOfOffset(position.getOffset());
+ int rulerLine = getInfo().getLineOfLastMouseButtonActivity();
+ if (rulerLine == markerLineNumber) {
+ return !getTextEditor().isDirty()
+ || aBreakpoint.getLineNumber() == markerLineNumber + 1;
+ }
+ } catch (BadLocationException x) {
+ // continue
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns the AbstractMarkerAnnotationModel of the editor's input.
+ *
+ * @return the marker annotation model
+ */
+ protected AbstractMarkerAnnotationModel getAnnotationModel() {
+ IDocumentProvider provider = textEditor.getDocumentProvider();
+ IAnnotationModel model = provider.getAnnotationModel(getTextEditor().getEditorInput());
+ if (model instanceof AbstractMarkerAnnotationModel) {
+ return (AbstractMarkerAnnotationModel)model;
+ }
+ return null;
+ }
+
+ /**
+ * Gets the resource for which to create the marker.
+ *
+ * @return the resource for which to create the marker or <code>null</code>
+ */
+ protected IResource getResource() {
+ IEditorInput input = textEditor.getEditorInput();
+ IResource resource = (IResource)input.getAdapter(IFile.class);
+ if (resource == null) {
+ resource = (IResource)input.getAdapter(IResource.class);
+ }
+ return resource;
+ }
+
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/actions/BreakpointSelectModelRulerAction.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/actions/BreakpointSelectModelRulerAction.java
new file mode 100644
index 0000000..99f100b
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/actions/BreakpointSelectModelRulerAction.java
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.debug.actions;
+
+import org.eclipse.acceleo.engine.internal.debug.ASTFragment;
+import org.eclipse.acceleo.ide.ui.AcceleoUIActivator;
+import org.eclipse.acceleo.internal.ide.ui.AcceleoUIMessages;
+import org.eclipse.acceleo.internal.ide.ui.debug.model.AcceleoLineBreakpoint;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.model.IBreakpoint;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.dialogs.InputDialog;
+import org.eclipse.jface.text.source.IVerticalRulerInfo;
+import org.eclipse.jface.window.Window;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+/**
+ * The breakpoint ruler action to set the condition. A breakpoint is valid only if the current model object
+ * validates this condition.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class BreakpointSelectModelRulerAction extends AbstractBreakpointRulerAction implements IAction {
+
+ /**
+ * The constructor.
+ *
+ * @param editor
+ * is the editor
+ * @param rulerInfo
+ * is the vertical ruler
+ */
+ public BreakpointSelectModelRulerAction(ITextEditor editor, IVerticalRulerInfo rulerInfo) {
+ setInfo(rulerInfo);
+ setTextEditor(editor);
+ setText(AcceleoUIMessages.getString("BreakpointSelectModelRulerAction.Text")); //$NON-NLS-1$
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.jface.action.Action#run()
+ */
+ @Override
+ public void run() {
+ IBreakpoint breakPoint = getBreakpoint();
+ if (breakPoint != null && breakPoint.getMarker() != null) {
+ try {
+ ASTFragment astFragment = new ASTFragment(breakPoint.getMarker().getAttribute(
+ AcceleoLineBreakpoint.AST_FRAGMENT, "")); //$NON-NLS-1$
+ InputDialog dialog = new InputDialog(
+ getTextEditor().getSite().getShell(),
+ AcceleoUIMessages.getString("BreakpointSelectModelRulerAction.Text"), AcceleoUIMessages.getString("BreakpointSelectModelRulerAction.DialogMessage"), astFragment.getEObjectNameFilter(), null); //$NON-NLS-1$ //$NON-NLS-2$
+ if (dialog.open() == Window.OK && dialog.getValue() != null) {
+ astFragment.setEObjectNameFilter(dialog.getValue());
+ breakPoint.getMarker().setAttribute(AcceleoLineBreakpoint.AST_FRAGMENT,
+ astFragment.toString());
+ }
+ } catch (CoreException e) {
+ AcceleoUIActivator.getDefault().getLog().log(e.getStatus());
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.ui.texteditor.IUpdate#update()
+ */
+ public void update() {
+ setBreakpoint(determineBreakpoint());
+ if (getBreakpoint() == null || !(getBreakpoint() instanceof AcceleoLineBreakpoint)) {
+ setBreakpoint(null);
+ setEnabled(false);
+ return;
+ }
+ setEnabled(true);
+ }
+
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/actions/RulerSelectModelActionDelegate.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/actions/RulerSelectModelActionDelegate.java
new file mode 100644
index 0000000..a206e18
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/actions/RulerSelectModelActionDelegate.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.debug.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.text.source.IVerticalRulerInfo;
+import org.eclipse.ui.texteditor.AbstractRulerActionDelegate;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+/**
+ * This class serves as an adapter for actions contributed to the vertical ruler's context menu.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class RulerSelectModelActionDelegate extends AbstractRulerActionDelegate {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.ui.texteditor.AbstractRulerActionDelegate#createAction(org.eclipse.ui.texteditor.ITextEditor,
+ * org.eclipse.jface.text.source.IVerticalRulerInfo)
+ */
+ protected IAction createAction(ITextEditor editor, IVerticalRulerInfo rulerInfo) {
+ return new BreakpointSelectModelRulerAction(editor, rulerInfo);
+ }
+
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/core/AcceleoDebugger.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/core/AcceleoDebugger.java
new file mode 100644
index 0000000..156cc85
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/core/AcceleoDebugger.java
@@ -0,0 +1,678 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.debug.core;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Stack;
+
+import org.eclipse.acceleo.common.utils.ModelUtils;
+import org.eclipse.acceleo.engine.internal.debug.ASTFragment;
+import org.eclipse.acceleo.engine.internal.debug.IDebugAST;
+import org.eclipse.acceleo.ide.ui.AcceleoUIActivator;
+import org.eclipse.acceleo.ide.ui.resources.AcceleoProject;
+import org.eclipse.acceleo.internal.parser.cst.utils.FileContent;
+import org.eclipse.acceleo.model.mtl.Module;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
+import org.eclipse.ocl.utilities.ASTNode;
+
+/**
+ * Template evaluation debugger to debug an Acceleo AST evaluation.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class AcceleoDebugger implements IDebugAST, ITemplateDebugger {
+
+ /**
+ * The current state of the debugger : RESULME or SUSPENDED.
+ */
+ private int state = ITemplateDebugger.RESUMED;
+
+ /**
+ * Indicates if the current action is to go into the next evaluation step.
+ */
+ private boolean stepInto = true;
+
+ /**
+ * Indicates if the current action is to go over the next evaluation step.
+ */
+ private boolean stepOver = true;
+
+ /**
+ * Indicates if the current action is to go to the parent evaluation step.
+ */
+ private boolean stepReturn = true;
+
+ /**
+ * Indicates if the thread is terminated.
+ */
+ private boolean terminated;
+
+ /**
+ * Contains the AST node fragments of all the available breakpoints.
+ */
+ private Set<ASTFragment> breakpointsASTFragments = new HashSet<ASTFragment>();
+
+ /**
+ * Contains all the AST node fragments of the project to debug. The map value is the position of the AST
+ * node in the Acceleo file.
+ */
+ private Map<ASTFragment, FileRegion> allASTFragments = new HashMap<ASTFragment, FileRegion>();
+
+ /**
+ * Debugger events listeners during a template evaluation.
+ */
+ private Set<ITemplateDebuggerListener> listeners = new HashSet<ITemplateDebuggerListener>();
+
+ /**
+ * The current stack of the debugger. It corresponds to the "Launch View" stack.
+ */
+ private Stack<StackInfo> stackDebugger = new Stack<StackInfo>();
+
+ /**
+ * The previous stack debugger size. It is useful to know if the stack grows or not.
+ */
+ private int stackDebuggerSize;
+
+ /**
+ * The position of the AST node in the Acceleo file : line, offset...
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+ private final class FileRegion {
+
+ /**
+ * The Acceleo file which contains the the AST node.
+ */
+ private File file;
+
+ /**
+ * The line of the AST node offset in the Acceleo file.
+ */
+ private int line;
+
+ /**
+ * The beginning index of the AST node.
+ */
+ private int start;
+
+ /**
+ * The ending index of the AST node.
+ */
+ private int end;
+
+ /**
+ * Constructor.
+ */
+ private FileRegion() {
+ super();
+ }
+
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param project
+ * is the project that contains the Acceleo Application to launch
+ */
+ public AcceleoDebugger(IProject project) {
+ init(project);
+ }
+
+ /**
+ * To initialize the debugger with every AST nodes of the accessible modules.
+ *
+ * @param project
+ * is the current Acceleo project
+ */
+ private void init(IProject project) {
+ ResourceSet oResourceSet = new ResourceSetImpl();
+ try {
+ Map<File, Module> mtlFiles = getInputOutputAcceleoFiles(project, oResourceSet);
+ breakpointsASTFragments.clear();
+ allASTFragments.clear();
+ Set<ASTFragment> conflicts = new HashSet<ASTFragment>();
+ Iterator<Map.Entry<File, Module>> mtlFilesIt = mtlFiles.entrySet().iterator();
+ while (mtlFilesIt.hasNext()) {
+ Map.Entry<File, Module> entry = mtlFilesIt.next();
+ File file = entry.getKey();
+ StringBuffer buffer = FileContent.getFileContent(file);
+ Module eModule = entry.getValue();
+ Iterator<EObject> eAllContents = eModule.eAllContents();
+ while (eAllContents.hasNext()) {
+ EObject eObject = eAllContents.next();
+ if (eObject instanceof ASTNode) {
+ ASTFragment fragment = new ASTFragment(eObject);
+ if (!conflicts.contains(fragment)) {
+ conflicts.add(fragment);
+ int start = ((ASTNode)eObject).getStartPosition();
+ int end = ((ASTNode)eObject).getEndPosition();
+ int line = lineNumber(buffer, start);
+ if (start > -1) {
+ FileRegion region = new FileRegion();
+ region.file = file;
+ region.line = line;
+ region.start = start;
+ region.end = end;
+ allASTFragments.put(fragment, region);
+ }
+ }
+ }
+ }
+ }
+ } finally {
+ Iterator<Resource> resources = oResourceSet.getResources().iterator();
+ while (resources.hasNext()) {
+ resources.next().unload();
+ }
+ }
+ state = ITemplateDebugger.RESUMED;
+ stepInto = false;
+ stepOver = false;
+ stepReturn = false;
+ terminated = false;
+ stackDebugger.clear();
+ }
+
+ /**
+ * Gets the Acceleo files of the given project and its dependencies. It also loads the corresponding AST model
+ * of each Acceleo file in the given resource set.
+ *
+ * @param project
+ * is the project that contains the Acceleo Application to launch
+ * @param oResourceSet
+ * is the resource set where to put the AST models.
+ * @return a map of the accessible Acceleo files and their corresponding AST models
+ */
+ private Map<File, Module> getInputOutputAcceleoFiles(IProject project, ResourceSet oResourceSet) {
+ Map<File, Module> result = new HashMap<File, Module>();
+ Iterator<AcceleoProject> acceleoProjects = new AcceleoProject(project).getRecursivelyAccessibleAcceleoProjects()
+ .iterator();
+ while (acceleoProjects.hasNext()) {
+ AcceleoProject acceleoProject = acceleoProjects.next();
+ try {
+ List<IFile> mtlFiles = acceleoProject.getInputFiles();
+ for (Iterator<IFile> iterator = mtlFiles.iterator(); iterator.hasNext();) {
+ IFile mtlFile = iterator.next();
+ IPath outputFilePath = acceleoProject.getOutputFilePath(mtlFile);
+ if (outputFilePath != null) {
+ URI outputFileURI = URI.createPlatformResourceURI(outputFilePath.toString(), false);
+ try {
+ EObject root = ModelUtils.load(outputFileURI, oResourceSet);
+ if (root instanceof Module) {
+ result.put(mtlFile.getLocation().toFile(), (Module)root);
+ }
+ } catch (IOException e1) {
+ AcceleoUIActivator.getDefault().getLog().log(
+ new Status(IStatus.ERROR, AcceleoUIActivator.PLUGIN_ID, e1.getMessage(), e1));
+ }
+ }
+ }
+ } catch (CoreException e2) {
+ AcceleoUIActivator.getDefault().getLog().log(e2.getStatus());
+ }
+ }
+ return result;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.acceleo.engine.internal.debug.IDebugAST#startDebug(org.eclipse.acceleo.engine.internal.debug.ASTFragment)
+ */
+ public void startDebug(ASTFragment astFragment) {
+ pushStack(astFragment);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.acceleo.engine.internal.debug.IDebugAST#stepDebugInput(org.eclipse.acceleo.engine.internal.debug.ASTFragment,
+ * java.lang.Object)
+ */
+ public void stepDebugInput(ASTFragment astFragment, Object input) {
+ if (isBreakpoint(astFragment, false)) {
+ final Map<String, Object> map = getInputVariables(input);
+ waitForEvent(map);
+ } else {
+ final Map<String, Object> map = getInputVariables(input);
+ updateVariables(map);
+ }
+ }
+
+ /**
+ * Gets the variables to show in the "Variables View" before a new step.
+ *
+ * @param input
+ * is the current object to evaluate
+ * @return a map that contains the variable names and their values
+ */
+ private Map<String, Object> getInputVariables(Object input) {
+ final Map<String, Object> map = new HashMap<String, Object>();
+ map.put("input", input); //$NON-NLS-1$
+ return map;
+ }
+
+ /**
+ * It updates the given variables.
+ *
+ * @param variables
+ * are the variables to show
+ */
+ public void updateVariables(Map<String, Object> variables) {
+ if (variables != null && !stackDebugger.isEmpty()) {
+ StackInfo stackInfo = stackDebugger.peek();
+ for (Iterator<String> iterator = variables.keySet().iterator(); iterator.hasNext();) {
+ String name = (String)iterator.next();
+ Object value = variables.get(name);
+ stackInfo.addVariable(name, value);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.acceleo.engine.internal.debug.IDebugAST#stepDebugOutput(org.eclipse.acceleo.engine.internal.debug.ASTFragment,
+ * java.lang.Object, java.lang.Object)
+ */
+ public void stepDebugOutput(ASTFragment astFragment, Object input, Object output) {
+ if (isBreakpoint(astFragment, true)) {
+ final Map<String, Object> map = new HashMap<String, Object>();
+ map.put("output", output); //$NON-NLS-1$
+ waitForEvent(map);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.acceleo.engine.internal.debug.IDebugAST#endDebug(org.eclipse.acceleo.engine.internal.debug.ASTFragment)
+ */
+ public void endDebug(ASTFragment astFragment) {
+ popStack(astFragment);
+ }
+
+ /**
+ * Returns the number of the line for the given offset.
+ *
+ * @param buffer
+ * is the buffer
+ * @param index
+ * is the offset in the buffer
+ * @return the line
+ */
+ private int lineNumber(final StringBuffer buffer, int index) {
+ if (buffer != null && index < buffer.length()) {
+ int line = 1;
+ for (int i = index - 1; i >= 0; i--) {
+ if (buffer.charAt(i) == '\n') {
+ line++;
+ }
+ }
+ return line;
+ } else {
+ return 0;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.acceleo.engine.debug.ITemplateDebugger#addBreakpoint(org.eclipse.acceleo.engine.internal.debug.ASTFragment)
+ */
+ public void addBreakpoint(ASTFragment astFragment) {
+ if (!astFragment.isEmpty()) {
+ breakpointsASTFragments.add(astFragment);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.acceleo.engine.debug.ITemplateDebugger#removeBreakpoint(org.eclipse.acceleo.engine.internal.debug.ASTFragment)
+ */
+ public void removeBreakpoint(ASTFragment astFragment) {
+ if (!astFragment.isEmpty()) {
+ breakpointsASTFragments.remove(astFragment);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.acceleo.engine.debug.ITemplateDebugger#addListener(org.eclipse.acceleo.engine.debug.ITemplateDebuggerListener)
+ */
+ public void addListener(ITemplateDebuggerListener aListener) {
+ listeners.add(aListener);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.acceleo.engine.debug.ITemplateDebugger#getState()
+ */
+ public int getState() {
+ return state;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.acceleo.engine.debug.ITemplateDebugger#removeListener(org.eclipse.acceleo.engine.debug.ITemplateDebuggerListener)
+ */
+ public void removeListener(ITemplateDebuggerListener aListener) {
+ listeners.remove(aListener);
+
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.acceleo.engine.debug.ITemplateDebugger#resume()
+ */
+ public void resume() {
+ stepInto = false;
+ stepOver = false;
+ stepReturn = false;
+ state = ITemplateDebugger.RESUMED;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.acceleo.engine.debug.ITemplateDebugger#stepInto()
+ */
+ public void stepInto() {
+ stepInto = true;
+ stepOver = false;
+ stepReturn = false;
+ state = ITemplateDebugger.RESUMED;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.acceleo.engine.debug.ITemplateDebugger#stepOver()
+ */
+ public void stepOver() {
+ stepInto = false;
+ stepOver = true;
+ stepReturn = false;
+ state = ITemplateDebugger.RESUMED;
+ stackDebuggerSize = stackDebugger.size();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.acceleo.engine.debug.ITemplateDebugger#stepReturn()
+ */
+ public void stepReturn() {
+ stepInto = false;
+ stepOver = false;
+ stepReturn = true;
+ state = ITemplateDebugger.RESUMED;
+ stackDebuggerSize = stackDebugger.size();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.acceleo.engine.debug.ITemplateDebugger#suspend()
+ */
+ public void suspend() {
+ stepInto = false;
+ stepOver = false;
+ stepReturn = false;
+ state = ITemplateDebugger.SUSPENDED;
+
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.acceleo.engine.debug.ITemplateDebugger#start()
+ */
+ public void start() {
+ fireStartEvent();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.acceleo.engine.debug.ITemplateDebugger#end()
+ */
+ public void end() {
+ fireEndEvent();
+ }
+
+ /**
+ * Indicates if there is a breakpoint for the given AST node.
+ *
+ * @param astFragment
+ * is an AST node fragment
+ * @param isOutputStep
+ * indicates if the debug step is an output step
+ * @return true if there is a breakpoint at the given position
+ */
+ private boolean isBreakpoint(ASTFragment astFragment, boolean isOutputStep) {
+ if (terminated) {
+ return false;
+ } else {
+ boolean ret = false;
+ if (stepInto) {
+ ret = true;
+ } else if (stepOver) {
+ if (stackDebugger.size() <= stackDebuggerSize) {
+ ret = true;
+ stackDebuggerSize = stackDebugger.size();
+ } else {
+ ret = false;
+ }
+ } else if (stepReturn) {
+ if (stackDebugger.size() < stackDebuggerSize) {
+ ret = true;
+ stackDebuggerSize = stackDebugger.size();
+ } else {
+ ret = false;
+ }
+ } else {
+ if (astFragment.isEmpty() || isOutputStep) {
+ ret = false;
+ } else {
+ ret = breakpointsASTFragments.contains(astFragment);
+ }
+ }
+ if (ret) {
+ state = SUSPENDED;
+ }
+ return ret;
+ }
+ }
+
+ /**
+ * Suspend on a breakpoint. Informs all debugger event listeners.
+ */
+ private void fireSuspendedBreakpointEvent() {
+ for (Iterator<ITemplateDebuggerListener> iterator = listeners.iterator(); iterator.hasNext();) {
+ ITemplateDebuggerListener debugListener = (ITemplateDebuggerListener)iterator.next();
+ debugListener.suspendBreakpoint();
+ }
+ }
+
+ /**
+ * Resume after client action. Informs all debugger event listeners.
+ */
+ private void fireResumedClientEvent() {
+ for (Iterator<ITemplateDebuggerListener> iterator = listeners.iterator(); iterator.hasNext();) {
+ ITemplateDebuggerListener debugListener = (ITemplateDebuggerListener)iterator.next();
+ debugListener.resumeClient();
+ }
+ }
+
+ /**
+ * Resume after one step. Informs all debugger event listeners.
+ */
+ private void fireResumedStepEvent() {
+ for (Iterator<ITemplateDebuggerListener> iterator = listeners.iterator(); iterator.hasNext();) {
+ ITemplateDebuggerListener debugListener = (ITemplateDebuggerListener)iterator.next();
+ debugListener.resumeStep();
+ }
+ }
+
+ /**
+ * Suspend after a step. Informs all debugger event listeners.
+ */
+ private void fireSuspendedStepEvent() {
+ for (Iterator<ITemplateDebuggerListener> iterator = listeners.iterator(); iterator.hasNext();) {
+ ITemplateDebuggerListener debugListener = (ITemplateDebuggerListener)iterator.next();
+ debugListener.suspendStep();
+ }
+ }
+
+ /**
+ * Beginning action. Informs all debugger event listeners.
+ */
+ private void fireStartEvent() {
+ for (Iterator<ITemplateDebuggerListener> iterator = listeners.iterator(); iterator.hasNext();) {
+ ITemplateDebuggerListener debugListener = (ITemplateDebuggerListener)iterator.next();
+ debugListener.start();
+ }
+ }
+
+ /**
+ * Ending action. Informs all debugger event listeners.
+ */
+ private void fireEndEvent() {
+ for (Iterator<ITemplateDebuggerListener> iterator = listeners.iterator(); iterator.hasNext();) {
+ ITemplateDebuggerListener debugListener = (ITemplateDebuggerListener)iterator.next();
+ debugListener.end();
+ }
+ }
+
+ /**
+ * It shows the given variables and it waits a user event.
+ *
+ * @param variables
+ * are the variables to show
+ */
+ public void waitForEvent(Map<String, Object> variables) {
+ if (state == SUSPENDED && !stackDebugger.isEmpty()) {
+ if (variables != null) {
+ StackInfo stackInfo = stackDebugger.peek();
+ for (Iterator<String> iterator = variables.keySet().iterator(); iterator.hasNext();) {
+ String name = (String)iterator.next();
+ Object value = variables.get(name);
+ stackInfo.addVariable(name, value);
+ }
+ }
+ if (stepInto || stepOver || stepReturn) {
+ fireSuspendedStepEvent();
+ } else {
+ fireSuspendedBreakpointEvent();
+ }
+ while (state == SUSPENDED) {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ // continue
+ }
+ }
+ if (stepInto || stepOver || stepReturn) {
+ fireResumedClientEvent();
+ } else {
+ fireResumedClientEvent();
+ fireResumedStepEvent();
+ }
+ try {
+ final int sleep = 300;
+ Thread.sleep(sleep);
+ } catch (InterruptedException e) {
+ // continue
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.acceleo.engine.debug.ITemplateDebugger#getStack()
+ */
+ public StackInfo[] getStack() {
+ StackInfo[] ret = new StackInfo[stackDebugger.size()];
+ int i = 0;
+ for (Iterator<StackInfo> iterator = stackDebugger.iterator(); iterator.hasNext();) {
+ StackInfo current = iterator.next();
+ ret[i] = current;
+ ++i;
+ }
+ return ret;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.acceleo.engine.debug.ITemplateDebugger#popStack(org.eclipse.acceleo.engine.internal.debug.ASTFragment)
+ */
+ public void popStack(ASTFragment astFragment) {
+ FileRegion fileRegion = allASTFragments.get(astFragment);
+ if (fileRegion != null) {
+ stackDebugger.pop();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.acceleo.engine.debug.ITemplateDebugger#pushStack(org.eclipse.acceleo.engine.internal.debug.ASTFragment)
+ */
+ public void pushStack(ASTFragment astFragment) {
+ FileRegion fileRegion = allASTFragments.get(astFragment);
+ if (fileRegion != null) {
+ StackInfo stackInfo = new StackInfo();
+ stackInfo.setFile(fileRegion.file);
+ stackInfo.setLine(fileRegion.line);
+ stackInfo.setCharStart(fileRegion.start);
+ stackInfo.setCharEnd(fileRegion.end);
+ stackDebugger.push(stackInfo);
+ }
+
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.acceleo.engine.debug.ITemplateDebugger#terminate()
+ */
+ public void terminate() {
+ terminated = true;
+ state = RESUMED;
+ }
+
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/core/ITemplateDebugger.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/core/ITemplateDebugger.java
new file mode 100644
index 0000000..03fffea
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/core/ITemplateDebugger.java
@@ -0,0 +1,134 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.debug.core;
+
+import org.eclipse.acceleo.engine.internal.debug.ASTFragment;
+
+/**
+ * Interface for a template evaluation debugger.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public interface ITemplateDebugger {
+
+ /**
+ * Resumed state.
+ */
+ int RESUMED = 0;
+
+ /**
+ * Suspended state.
+ */
+ int SUSPENDED = 1;
+
+ /**
+ * To resume the evaluation of the current template.
+ */
+ void resume();
+
+ /**
+ * To suspend the evaluation of the current template.
+ */
+ void suspend();
+
+ /**
+ * Go into the next evaluation step.
+ */
+ void stepInto();
+
+ /**
+ * Go over the next evaluation step.
+ */
+ void stepOver();
+
+ /**
+ * Go to the parent evaluation step.
+ */
+ void stepReturn();
+
+ /**
+ * Terminate the evaluation.
+ */
+ void terminate();
+
+ /**
+ * Adds a breakpoint.
+ *
+ * @param astFragment
+ * the fragment URI of an AST node
+ */
+ void addBreakpoint(ASTFragment astFragment);
+
+ /**
+ * Removes a breakpoint.
+ *
+ * @param astFragment
+ * the fragment URI of an AST node
+ */
+ void removeBreakpoint(ASTFragment astFragment);
+
+ /**
+ * Returns the state of the debugger.
+ *
+ * @return the state of the debugger
+ */
+ int getState();
+
+ /**
+ * Adds a template listener.
+ *
+ * @param aListener
+ * is the listener to add
+ */
+ void addListener(ITemplateDebuggerListener aListener);
+
+ /**
+ * Removes a template listener.
+ *
+ * @param aListener
+ * is the listener to remove
+ */
+ void removeListener(ITemplateDebuggerListener aListener);
+
+ /**
+ * To start the debugger.
+ */
+ void start();
+
+ /**
+ * To finish the debugger.
+ */
+ void end();
+
+ /**
+ * Returns the current execution stack.
+ *
+ * @return the execution stack
+ */
+ StackInfo[] getStack();
+
+ /**
+ * Pushes a new execution context.
+ *
+ * @param astFragment
+ * the fragment URI of an AST node
+ */
+ void pushStack(ASTFragment astFragment);
+
+ /**
+ * Pops the last added execution context.
+ *
+ * @param astFragment
+ * the fragment URI of an AST node
+ */
+ void popStack(ASTFragment astFragment);
+
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/core/ITemplateDebuggerListener.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/core/ITemplateDebuggerListener.java
new file mode 100644
index 0000000..fe100a0
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/core/ITemplateDebuggerListener.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.debug.core;
+
+/**
+ * Debugger events listener during a template evaluation.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public interface ITemplateDebuggerListener {
+
+ /**
+ * Resume after client action.
+ */
+ void resumeClient();
+
+ /**
+ * Resume after one step.
+ */
+ void resumeStep();
+
+ /**
+ * Suspend on a breakpoint.
+ */
+ void suspendBreakpoint();
+
+ /**
+ * Suspend after a step.
+ */
+ void suspendStep();
+
+ /**
+ * Beginning action.
+ */
+ void start();
+
+ /**
+ * Ending action.
+ */
+ void end();
+
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/core/StackInfo.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/core/StackInfo.java
new file mode 100644
index 0000000..71e3ebb
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/core/StackInfo.java
@@ -0,0 +1,149 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.debug.core;
+
+import java.io.File;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * Item of the debugger execution stack. The debugger stack is shown in the "Launch View". Each item is
+ * characterized by a line in an Acceleo file and a set of variables.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class StackInfo {
+
+ /**
+ * The current Acceleo file.
+ */
+ private File file;
+
+ /**
+ * A line in the Acceleo file.
+ */
+ private int line;
+
+ /**
+ * The beginning character of the current AST node of the Acceleo file.
+ */
+ private int charStart;
+
+ /**
+ * The ending character of the current AST node of the Acceleo file.
+ */
+ private int charEnd;
+
+ /**
+ * The variables to show in the "Variables View" before an input step or after an output step. This map
+ * contains the variable names and their values.
+ */
+ private Map<String, Object> variables = new LinkedHashMap<String, Object>();
+
+ /**
+ * Gets the current Acceleo file.
+ *
+ * @return the template file
+ */
+ public File getFile() {
+ return file;
+ }
+
+ /**
+ * Sets the current Acceleo file.
+ *
+ * @param file
+ * is the template file
+ */
+ public void setFile(File file) {
+ this.file = file;
+ }
+
+ /**
+ * Gets the line in the Acceleo file.
+ *
+ * @return the line in the Acceleo file
+ */
+ public int getLine() {
+ return line;
+ }
+
+ /**
+ * Sets the line in the Acceleo file.
+ *
+ * @param line
+ * is the line in the template file
+ */
+ public void setLine(int line) {
+ this.line = line;
+ }
+
+ /**
+ * Gets the beginning character of the current AST node of the Acceleo file.
+ *
+ * @return the index of the first character
+ */
+ public int getCharStart() {
+ return charStart;
+ }
+
+ /**
+ * Sets the beginning character of the current AST node of the Acceleo file.
+ *
+ * @param charStart
+ * is the index of the first character
+ */
+ public void setCharStart(int charStart) {
+ this.charStart = charStart;
+ }
+
+ /**
+ * Gets the ending character of the current AST node of the Acceleo file.
+ *
+ * @return the index of the last character
+ */
+ public int getCharEnd() {
+ return charEnd;
+ }
+
+ /**
+ * Sets the ending character of the current AST node of the Acceleo file.
+ *
+ * @param charEnd
+ * is the index of the last character
+ */
+ public void setCharEnd(int charEnd) {
+ this.charEnd = charEnd;
+ }
+
+ /**
+ * Adds a new variable for the given name and the given value. It will be shown in the "Variables View"
+ * before an input step or after an output step.
+ *
+ * @param aName
+ * is the name of the new variable
+ * @param aValue
+ * is the value of the new variable
+ */
+ public void addVariable(String aName, Object aValue) {
+ variables.put(aName, aValue);
+ }
+
+ /**
+ * Gets the variables to show in the "Variables View" before an input step or after an output step. It
+ * returns a map that contains the variable names and their values.
+ *
+ * @return the variables of the execution context
+ */
+ public Map<String, Object> getVariables() {
+ return variables;
+ }
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AbstractDebugElement.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AbstractDebugElement.java
new file mode 100644
index 0000000..a5e7ed4
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AbstractDebugElement.java
@@ -0,0 +1,161 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.debug.model;
+
+import org.eclipse.acceleo.ide.ui.AcceleoUIActivator;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.PlatformObject;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.debug.core.DebugEvent;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.IBreakpointManager;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.model.IDebugElement;
+import org.eclipse.debug.core.model.IDebugTarget;
+
+/**
+ * An Acceleo debug model element. Common abstract class for the debug target, the process, the stack frame, the
+ * thread...
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public abstract class AbstractDebugElement extends PlatformObject implements IDebugElement {
+
+ /**
+ * Containing target.
+ */
+ protected IDebugTarget fTarget;
+
+ /**
+ * Constructs a new debug element contained in the given debug target.
+ *
+ * @param target
+ * debug target (Acceleo VM)
+ */
+ public AbstractDebugElement(IDebugTarget target) {
+ fTarget = target;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IDebugElement#getModelIdentifier()
+ */
+ public String getModelIdentifier() {
+ return AcceleoModelPresentation.ID_ACCELEO_DEBUG_MODEL;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IDebugElement#getDebugTarget()
+ */
+ public IDebugTarget getDebugTarget() {
+ return fTarget;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IDebugElement#getLaunch()
+ */
+ public ILaunch getLaunch() {
+ return getDebugTarget().getLaunch();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.core.runtime.PlatformObject#getAdapter(java.lang.Class)
+ */
+ @SuppressWarnings("unchecked")
+ public Object getAdapter(Class adapter) {
+ Object result;
+ if (adapter == IDebugElement.class) {
+ result = this;
+ } else if (adapter == ILaunch.class) {
+ result = getLaunch();
+ } else {
+ result = super.getAdapter(adapter);
+ }
+ return result;
+ }
+
+ /**
+ * Throws a debug exception.
+ *
+ * @param message
+ * is the message
+ * @param e
+ * is the exception
+ * @throws DebugException
+ * the given message is used to create and throw a new debug exception
+ */
+ protected void abort(String message, Throwable e) throws DebugException {
+ throw new DebugException(new Status(IStatus.ERROR, AcceleoUIActivator.PLUGIN_ID,
+ DebugPlugin.INTERNAL_ERROR, message, e));
+ }
+
+ /**
+ * Notifies all registered debug event set listeners of the given debug event.
+ *
+ * @param event
+ * the event to be fired
+ */
+ protected void fireEvent(DebugEvent event) {
+ DebugPlugin.getDefault().fireDebugEventSet(new DebugEvent[] {event});
+ }
+
+ /**
+ * Fires a <code>CREATE</code> event for this element.
+ */
+ protected void fireCreationEvent() {
+ fireEvent(new DebugEvent(this, DebugEvent.CREATE));
+ }
+
+ /**
+ * Fires a <code>RESUME</code> event for this element with the given detail.
+ *
+ * @param detail
+ * event detail code
+ */
+ public void fireResumeEvent(int detail) {
+ fireEvent(new DebugEvent(this, DebugEvent.RESUME, detail));
+ }
+
+ /**
+ * Fires a <code>SUSPEND</code> event for this element with the given detail.
+ *
+ * @param detail
+ * event detail code
+ */
+ public void fireSuspendEvent(int detail) {
+ fireEvent(new DebugEvent(this, DebugEvent.SUSPEND, detail));
+ }
+
+ /**
+ * Fires a <code>TERMINATE</code> event for this element.
+ */
+ protected void fireTerminateEvent() {
+ fireEvent(new DebugEvent(this, DebugEvent.TERMINATE));
+ }
+
+ /**
+ * Returns the breakpoint manager.
+ *
+ * @return the breakpoint manager
+ * @see IBreakpointManager
+ */
+ protected IBreakpointManager getBreakpointManager() {
+ return DebugPlugin.getDefault().getBreakpointManager();
+ }
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoBreakpointAdapterFactory.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoBreakpointAdapterFactory.java
new file mode 100644
index 0000000..e5b52b5
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoBreakpointAdapterFactory.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.debug.model;
+
+import org.eclipse.acceleo.common.IAcceleoConstants;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IAdapterFactory;
+import org.eclipse.debug.ui.actions.IRunToLineTarget;
+import org.eclipse.debug.ui.actions.IToggleBreakpointsTarget;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+/**
+ * Creates a toggle breakpoint adapter factory. This factory is used to create a new Acceleo breakpoint.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class AcceleoBreakpointAdapterFactory implements IAdapterFactory {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.core.runtime.IAdapterFactory#getAdapter(java.lang.Object, java.lang.Class)
+ */
+ @SuppressWarnings("unchecked")
+ public Object getAdapter(Object adaptableObject, Class adapterType) {
+ Object adapter = null;
+ if (adaptableObject instanceof ITextEditor) {
+ ITextEditor editorPart = (ITextEditor)adaptableObject;
+ IResource resource = (IResource)editorPart.getEditorInput().getAdapter(IResource.class);
+ if (resource != null && IAcceleoConstants.MTL_FILE_EXTENSION.equals(resource.getFileExtension())) {
+ if (adapterType.equals(IToggleBreakpointsTarget.class)) {
+ adapter = new AcceleoLineBreakpointAdapter();
+ } else if (adapterType.equals(IRunToLineTarget.class)) {
+ adapter = new AcceleoRunToLineAdapter();
+ }
+ }
+ }
+ return adapter;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.core.runtime.IAdapterFactory#getAdapterList()
+ */
+ public Class<?>[] getAdapterList() {
+ return new Class[] {IToggleBreakpointsTarget.class};
+ }
+
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoDebugTarget.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoDebugTarget.java
new file mode 100644
index 0000000..03b9bed
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoDebugTarget.java
@@ -0,0 +1,474 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.debug.model;
+
+import org.eclipse.acceleo.ide.ui.AcceleoUIActivator;
+import org.eclipse.acceleo.internal.ide.ui.debug.core.ITemplateDebugger;
+import org.eclipse.acceleo.internal.ide.ui.debug.core.ITemplateDebuggerListener;
+import org.eclipse.core.resources.IMarkerDelta;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.DebugEvent;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.IBreakpointManager;
+import org.eclipse.debug.core.IBreakpointManagerListener;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.model.IBreakpoint;
+import org.eclipse.debug.core.model.IDebugTarget;
+import org.eclipse.debug.core.model.IMemoryBlock;
+import org.eclipse.debug.core.model.IProcess;
+import org.eclipse.debug.core.model.IThread;
+
+/**
+ * This is a debuggable execution context for an Acceleo Application. A debug target may represent a debuggable
+ * process or a virtual machine. A debug target is the root of the debug element hierarchy. A debug target
+ * contains threads. Minimally, a debug target supports the following:
+ * <ul>
+ * <li>terminate
+ * <li>suspend/resume
+ * <li>breakpoints
+ * <li>disconnect
+ * </ul>
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class AcceleoDebugTarget extends AbstractDebugElement implements IDebugTarget, IBreakpointManagerListener {
+
+ /**
+ * The process.
+ */
+ private AcceleoProcess process;
+
+ /**
+ * The thread.
+ */
+ private AcceleoThread thread;
+
+ /**
+ * The current launch configuration which is the result of launching a debug session.
+ */
+ private ILaunch launch;
+
+ /**
+ * The template evaluation debugger.
+ */
+ private ITemplateDebugger debugger;
+
+ /**
+ * Indicates if the thread is terminated.
+ */
+ private boolean terminated;
+
+ /**
+ * The debugger events listener during a template evaluation.
+ */
+ private ITemplateDebuggerListener debuggerListener;
+
+ /**
+ * Debugger target events listener.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+ private class TemplateDebuggerListener implements ITemplateDebuggerListener {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.acceleo.ide.ui.debug.core.ITemplateDebuggerListener#resumeClient()
+ */
+ public void resumeClient() {
+ thread.setSuspended(false);
+ thread.setStepping(false);
+ thread.fireResumeEvent(DebugEvent.CLIENT_REQUEST);
+
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.acceleo.ide.ui.debug.core.ITemplateDebuggerListener#suspendBreakpoint()
+ */
+ public void suspendBreakpoint() {
+ thread.setSuspended(true);
+ thread.setStepping(false);
+ thread.fireSuspendEvent(DebugEvent.BREAKPOINT);
+
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.acceleo.ide.ui.debug.core.ITemplateDebuggerListener#resumeStep()
+ */
+ public void resumeStep() {
+ thread.setSuspended(false);
+ thread.setStepping(true);
+ thread.fireResumeEvent(DebugEvent.STEP_OVER);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.acceleo.ide.ui.debug.core.ITemplateDebuggerListener#suspendStep()
+ */
+ public void suspendStep() {
+ thread.setSuspended(true);
+ thread.setStepping(false);
+ thread.fireSuspendEvent(DebugEvent.STEP_END);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.acceleo.ide.ui.debug.core.ITemplateDebuggerListener#start()
+ */
+ public void start() {
+ thread.fireCreationEvent();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.acceleo.ide.ui.debug.core.ITemplateDebuggerListener#end()
+ */
+ public void end() {
+ try {
+ terminate();
+ } catch (DebugException e) {
+ AcceleoUIActivator.getDefault().getLog().log(e.getStatus());
+ }
+ }
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param aLaunch
+ * is the current launch configuration
+ * @param aTemplateDebugger
+ * is the template evaluation debugger
+ */
+ public AcceleoDebugTarget(ILaunch aLaunch, ITemplateDebugger aTemplateDebugger) {
+ super(null);
+ launch = aLaunch;
+ debugger = aTemplateDebugger;
+ process = new AcceleoProcess(this);
+ launch.addProcess(process);
+ thread = new AcceleoThread(this);
+ IBreakpointManager breakpointManager = getBreakpointManager();
+ breakpointManager.addBreakpointListener(this);
+ breakpointManager.addBreakpointManagerListener(this);
+ IBreakpoint[] breakpoints = getBreakpointManager().getBreakpoints();
+ for (int i = 0; i < breakpoints.length; ++i) {
+ if (breakpoints[i] instanceof AcceleoLineBreakpoint) {
+ AcceleoLineBreakpoint lineBreakpoint = (AcceleoLineBreakpoint)breakpoints[i];
+ try {
+ if (lineBreakpoint.isEnabled()) {
+ debugger.addBreakpoint(lineBreakpoint.getASTFragment());
+ }
+ } catch (CoreException e) {
+ AcceleoUIActivator.getDefault().getLog().log(e.getStatus());
+ }
+ }
+ }
+ debuggerListener = new TemplateDebuggerListener();
+ debugger.addListener(debuggerListener);
+ }
+
+ /**
+ * Gets the template evaluation debugger.
+ *
+ * @return the template evaluation debugger
+ */
+ public ITemplateDebugger getDebugger() {
+ return debugger;
+ }
+
+ /**
+ * Go into the next evaluation step.
+ */
+ public void stepInto() {
+ debugger.stepInto();
+
+ }
+
+ /**
+ * Go over the next evaluation step.
+ */
+ public void stepOver() {
+ debugger.stepOver();
+
+ }
+
+ /**
+ * Go to the parent evaluation step.
+ */
+ public void stepReturn() {
+ debugger.stepReturn();
+
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.acceleo.ide.ui.debug.model.AbstractDebugElement#getLaunch()
+ */
+ public ILaunch getLaunch() {
+ return launch;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IDebugTarget#getName()
+ */
+ public String getName() throws DebugException {
+ return process.getLabel();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IDebugTarget#getProcess()
+ */
+ public IProcess getProcess() {
+ return process;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IDebugTarget#getThreads()
+ */
+ public IThread[] getThreads() throws DebugException {
+ IThread[] ret;
+ if (thread != null) {
+ ret = new IThread[] {thread};
+ } else {
+ ret = new IThread[] {};
+ }
+ return ret;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IDebugTarget#hasThreads()
+ */
+ public boolean hasThreads() throws DebugException {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IDebugTarget#supportsBreakpoint(org.eclipse.debug.core.model.IBreakpoint)
+ */
+ public boolean supportsBreakpoint(IBreakpoint breakpoint) {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.ITerminate#canTerminate()
+ */
+ public boolean canTerminate() {
+ return !terminated;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.ITerminate#isTerminated()
+ */
+ public boolean isTerminated() {
+ return terminated;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.ITerminate#terminate()
+ */
+ public void terminate() throws DebugException {
+ thread = null;
+ terminated = true;
+ fireTerminateEvent();
+ debugger.terminate();
+ debugger.removeListener(debuggerListener);
+ IBreakpointManager breakpointManager = getBreakpointManager();
+ breakpointManager.removeBreakpointListener(this);
+ breakpointManager.removeBreakpointManagerListener(this);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.ISuspendResume#canResume()
+ */
+ public boolean canResume() {
+ return !isTerminated();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.ISuspendResume#canSuspend()
+ */
+ public boolean canSuspend() {
+ return !isTerminated();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.ISuspendResume#isSuspended()
+ */
+ public boolean isSuspended() {
+ return !isTerminated() && thread.isSuspended();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.ISuspendResume#resume()
+ */
+ public void resume() throws DebugException {
+ debugger.resume();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.ISuspendResume#suspend()
+ */
+ public void suspend() throws DebugException {
+ debugger.suspend();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.IBreakpointListener#breakpointAdded(org.eclipse.debug.core.model.IBreakpoint)
+ */
+ public void breakpointAdded(IBreakpoint breakpoint) {
+ if (breakpoint instanceof AcceleoLineBreakpoint) {
+ AcceleoLineBreakpoint acceleoLineBreakpoint = (AcceleoLineBreakpoint)breakpoint;
+ debugger.addBreakpoint(acceleoLineBreakpoint.getASTFragment());
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.IBreakpointListener#breakpointChanged(org.eclipse.debug.core.model.IBreakpoint,
+ * org.eclipse.core.resources.IMarkerDelta)
+ */
+ public void breakpointChanged(IBreakpoint breakpoint, IMarkerDelta delta) {
+ if (breakpoint instanceof AcceleoLineBreakpoint) {
+ AcceleoLineBreakpoint acceleoLineBreakpoint = (AcceleoLineBreakpoint)breakpoint;
+ try {
+ if (acceleoLineBreakpoint.isEnabled()) {
+ debugger.addBreakpoint(acceleoLineBreakpoint.getASTFragment());
+ } else {
+ debugger.removeBreakpoint(acceleoLineBreakpoint.getASTFragment());
+ }
+ } catch (CoreException e) {
+ AcceleoUIActivator.getDefault().getLog().log(e.getStatus());
+ }
+ }
+
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.IBreakpointListener#breakpointRemoved(org.eclipse.debug.core.model.IBreakpoint,
+ * org.eclipse.core.resources.IMarkerDelta)
+ */
+ public void breakpointRemoved(IBreakpoint breakpoint, IMarkerDelta delta) {
+ if (breakpoint instanceof AcceleoLineBreakpoint) {
+ AcceleoLineBreakpoint acceleoLineBreakpoint = (AcceleoLineBreakpoint)breakpoint;
+ debugger.removeBreakpoint(acceleoLineBreakpoint.getASTFragment());
+ }
+
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IDisconnect#canDisconnect()
+ */
+ public boolean canDisconnect() {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IDisconnect#disconnect()
+ */
+ public void disconnect() throws DebugException {
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IDisconnect#isDisconnected()
+ */
+ public boolean isDisconnected() {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IMemoryBlockRetrieval#getMemoryBlock(long, long)
+ */
+ public IMemoryBlock getMemoryBlock(long startAddress, long length) throws DebugException {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IMemoryBlockRetrieval#supportsStorageRetrieval()
+ */
+ public boolean supportsStorageRetrieval() {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.IBreakpointManagerListener#breakpointManagerEnablementChanged(boolean)
+ */
+ public void breakpointManagerEnablementChanged(boolean enabled) {
+ IBreakpoint[] breakpoints = getBreakpointManager().getBreakpoints(getModelIdentifier());
+ for (int i = 0; i < breakpoints.length; i++) {
+ if (enabled) {
+ breakpointAdded(breakpoints[i]);
+ } else {
+ breakpointRemoved(breakpoints[i], null);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.acceleo.ide.ui.debug.model.AbstractDebugElement#getDebugTarget()
+ */
+ public IDebugTarget getDebugTarget() {
+ return this;
+ }
+
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoLineBreakpoint.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoLineBreakpoint.java
new file mode 100644
index 0000000..af2967e
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoLineBreakpoint.java
@@ -0,0 +1,140 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.debug.model;
+
+import java.io.File;
+
+import org.eclipse.acceleo.engine.internal.debug.ASTFragment;
+import org.eclipse.acceleo.internal.ide.ui.AcceleoUIMessages;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.IBreakpointManager;
+import org.eclipse.debug.core.model.IBreakpoint;
+import org.eclipse.debug.core.model.LineBreakpoint;
+import org.eclipse.emf.ecore.EObject;
+
+/**
+ * Acceleo implementation of a line breakpoint.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class AcceleoLineBreakpoint extends LineBreakpoint {
+
+ /**
+ * The line breakpoint marker ID.
+ */
+ public static final String MARKER_ID = "org.eclipse.acceleo.ide.ui.debug.markerType.lineBreakpoint"; //$NON-NLS-1$
+
+ /**
+ * AST node breakpoint marker attribute. This marker attribute is used to get the URI fragment of the AST
+ * node associated with this breakpoint.
+ */
+ public static final String AST_FRAGMENT = "astFragment"; //$NON-NLS-1$
+
+ /**
+ * Default constructor is required for the breakpoint manager to re-create persisted breakpoints. After
+ * instantiating a breakpoint, the <code>setMarker(...)</code> method is called to restore this
+ * breakpoint's attributes.
+ */
+ public AcceleoLineBreakpoint() {
+ }
+
+ /**
+ * Constructs a line breakpoint on the given resource at the given line number. The line number is 1-based
+ * (i.e. the first line of a file is line number 1). The Acceleo VM uses 0-based line numbers, so this line
+ * number translation is done at breakpoint install time.
+ *
+ * @param astNode
+ * is the AST node to associate with the breakpoint.
+ * @param resource
+ * file on which to set the breakpoint
+ * @param lineNumber
+ * 1-based line number of the breakpoint
+ * @param offset
+ * offset of the breakpoint
+ * @param length
+ * length of the breakpoint
+ * @throws CoreException
+ * when an issue occurs
+ */
+ public AcceleoLineBreakpoint(final EObject astNode, final IResource resource, final int lineNumber,
+ final int offset, final int length) throws CoreException {
+ IWorkspaceRunnable runnable = new IWorkspaceRunnable() {
+ public void run(IProgressMonitor monitor) throws CoreException {
+ IMarker marker = resource.createMarker(MARKER_ID);
+ setMarker(marker);
+ marker.setAttribute(IBreakpoint.ENABLED, Boolean.TRUE);
+ marker.setAttribute(IMarker.LINE_NUMBER, lineNumber);
+ marker.setAttribute(IBreakpoint.ID, getModelIdentifier());
+ marker.setAttribute(IMarker.CHAR_START, offset);
+ marker.setAttribute(IMarker.CHAR_END, offset + length);
+ marker.setAttribute(AST_FRAGMENT, new ASTFragment(astNode).toString());
+ marker
+ .setAttribute(
+ IMarker.MESSAGE,
+ AcceleoUIMessages
+ .getString(
+ "AcceleoLineBreakpoint.HoverText", new Object[] {astNode.eClass().getName(), resource.getName(), Integer.toString(lineNumber),})); //$NON-NLS-1$
+ }
+ };
+ run(getMarkerRule(resource), runnable);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IBreakpoint#getModelIdentifier()
+ */
+ public String getModelIdentifier() {
+ return AcceleoModelPresentation.ID_ACCELEO_DEBUG_MODEL;
+ }
+
+ /**
+ * Returns the current template file.
+ *
+ * @return the current template file
+ */
+ public File getFile() {
+ File ret = null;
+ if (getMarker().getResource() instanceof IFile) {
+ ret = ((IFile)getMarker().getResource()).getLocation().toFile();
+ }
+ return ret;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.Breakpoint#setEnabled(boolean)
+ */
+ public void setEnabled(boolean enabled) throws CoreException {
+ super.setEnabled(enabled);
+ IBreakpointManager breakpointManager = DebugPlugin.getDefault().getBreakpointManager();
+ if (breakpointManager != null) {
+ breakpointManager.fireBreakpointChanged(this);
+ }
+ }
+
+ /**
+ * Gets the URI fragment of the AST node associated with this breakpoint.
+ *
+ * @return the URI fragment of the AST node
+ */
+ public ASTFragment getASTFragment() {
+ return new ASTFragment(getMarker().getAttribute(AST_FRAGMENT, "")); //$NON-NLS-1$
+ }
+
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoLineBreakpointAdapter.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoLineBreakpointAdapter.java
new file mode 100644
index 0000000..c2709b1
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoLineBreakpointAdapter.java
@@ -0,0 +1,186 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.debug.model;
+
+import org.eclipse.acceleo.common.IAcceleoConstants;
+import org.eclipse.acceleo.internal.ide.ui.editors.template.AcceleoEditor;
+import org.eclipse.acceleo.internal.ide.ui.editors.template.AcceleoSourceContent;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.model.IBreakpoint;
+import org.eclipse.debug.core.model.ILineBreakpoint;
+import org.eclipse.debug.ui.actions.IToggleBreakpointsTarget;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ocl.utilities.ASTNode;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+/**
+ * Adapter to create breakpoints in Acceleo files.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class AcceleoLineBreakpointAdapter implements IToggleBreakpointsTarget {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTarget#toggleLineBreakpoints(org.eclipse.ui.IWorkbenchPart,
+ * org.eclipse.jface.viewers.ISelection)
+ */
+ public void toggleLineBreakpoints(IWorkbenchPart part, ISelection selection) throws CoreException {
+ ITextEditor textEditor = getEditor(part);
+ if (textEditor instanceof AcceleoEditor) {
+ AcceleoEditor acceleoEditor = (AcceleoEditor)textEditor;
+ IResource resource = (IResource)textEditor.getEditorInput().getAdapter(IResource.class);
+ ITextSelection textSelection = (ITextSelection)selection;
+ int lineNumber = textSelection.getStartLine();
+ int offset = textSelection.getOffset();
+ int length = textSelection.getLength();
+ if (offset == -1) {
+ return;
+ }
+ IBreakpoint[] breakpoints = DebugPlugin.getDefault().getBreakpointManager().getBreakpoints(
+ AcceleoModelPresentation.ID_ACCELEO_DEBUG_MODEL);
+ for (int i = 0; i < breakpoints.length; i++) {
+ IBreakpoint breakpoint = breakpoints[i];
+ if (resource.equals(breakpoint.getMarker().getResource())) {
+ int bLineNumber = ((ILineBreakpoint)breakpoint).getLineNumber();
+ int bCharStart = ((ILineBreakpoint)breakpoint).getCharStart();
+ int bCharEnd = ((ILineBreakpoint)breakpoint).getCharEnd();
+ if (bLineNumber == lineNumber + 1 || bCharStart == offset
+ || (offset <= bCharStart && offset + length >= bCharEnd)) {
+ // remove
+ breakpoint.delete();
+ return;
+ }
+ }
+ }
+ // create line breakpoint (line numbers start at 0)
+ ASTNode astNode = getBreakpointASTNodeAt(acceleoEditor.getContent(), offset);
+ if (astNode != null) {
+ AcceleoLineBreakpoint lineBreakpoint = new AcceleoLineBreakpoint(astNode, resource, lineNumber + 1,
+ offset, length);
+ DebugPlugin.getDefault().getBreakpointManager().addBreakpoint(lineBreakpoint);
+ }
+ }
+ }
+
+ /**
+ * Gets the nearest debuggable AST node at the given position.
+ *
+ * @param content
+ * is the Acceleo source content
+ * @param offset
+ * is the offset of the breakpoint to create
+ * @return the nearest debuggable AST node
+ */
+ protected static ASTNode getBreakpointASTNodeAt(AcceleoSourceContent content, int offset) {
+ int i = offset;
+ while (i > 0 && content.getText().charAt(i - 1) != '\n') {
+ i--;
+ }
+ while (i < content.getText().length()) {
+ char c = content.getText().charAt(i);
+ if (c == '\n') {
+ i = -1;
+ break;
+ } else if (c == '[') {
+ i += 2;
+ break;
+ } else {
+ i++;
+ }
+ }
+ ASTNode astNode = content.getASTNode(i, i);
+ if (astNode != null) {
+ while (astNode.eContainer() instanceof ASTNode
+ && ((ASTNode)astNode.eContainer()).getStartPosition() == astNode.getStartPosition()) {
+ astNode = (ASTNode)astNode.eContainer();
+ }
+ }
+ return astNode;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTarget#canToggleLineBreakpoints(org.eclipse.ui.IWorkbenchPart,
+ * org.eclipse.jface.viewers.ISelection)
+ */
+ public boolean canToggleLineBreakpoints(IWorkbenchPart part, ISelection selection) {
+ return getEditor(part) != null;
+ }
+
+ /**
+ * Returns the editor being used to edit a Acceleo file, associated with the given part, or <code>null</code>
+ * if none.
+ *
+ * @param part
+ * workbench part
+ * @return the editor being used to edit a Acceleo file, associated with the given part, or <code>null</code>
+ * if none
+ */
+ private ITextEditor getEditor(IWorkbenchPart part) {
+ if (part instanceof ITextEditor) {
+ ITextEditor editorPart = (ITextEditor)part;
+ IResource resource = (IResource)editorPart.getEditorInput().getAdapter(IResource.class);
+ if (resource != null) {
+ String extension = resource.getFileExtension();
+ if (IAcceleoConstants.MTL_FILE_EXTENSION.equals(extension)) {
+ return editorPart;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTarget#toggleMethodBreakpoints(org.eclipse.ui.IWorkbenchPart,
+ * org.eclipse.jface.viewers.ISelection)
+ */
+ public void toggleMethodBreakpoints(IWorkbenchPart part, ISelection selection) throws CoreException {
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTarget#canToggleMethodBreakpoints(org.eclipse.ui.IWorkbenchPart,
+ * org.eclipse.jface.viewers.ISelection)
+ */
+ public boolean canToggleMethodBreakpoints(IWorkbenchPart part, ISelection selection) {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTarget#toggleWatchpoints(org.eclipse.ui.IWorkbenchPart,
+ * org.eclipse.jface.viewers.ISelection)
+ */
+ public void toggleWatchpoints(IWorkbenchPart part, ISelection selection) throws CoreException {
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTarget#canToggleWatchpoints(org.eclipse.ui.IWorkbenchPart,
+ * org.eclipse.jface.viewers.ISelection)
+ */
+ public boolean canToggleWatchpoints(IWorkbenchPart part, ISelection selection) {
+ return false;
+ }
+
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoModelPresentation.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoModelPresentation.java
new file mode 100644
index 0000000..619f71e
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoModelPresentation.java
@@ -0,0 +1,202 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.debug.model;
+
+import java.io.File;
+
+import org.eclipse.acceleo.common.IAcceleoConstants;
+import org.eclipse.acceleo.engine.internal.debug.ASTFragment;
+import org.eclipse.acceleo.ide.ui.AcceleoUIActivator;
+import org.eclipse.acceleo.internal.ide.ui.AcceleoUIMessages;
+import org.eclipse.acceleo.internal.ide.ui.editors.template.AcceleoEditor;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.model.IDebugTarget;
+import org.eclipse.debug.core.model.ILineBreakpoint;
+import org.eclipse.debug.core.model.IProcess;
+import org.eclipse.debug.core.model.IThread;
+import org.eclipse.debug.core.model.IValue;
+import org.eclipse.debug.ui.IDebugModelPresentation;
+import org.eclipse.debug.ui.IValueDetailListener;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.part.FileEditorInput;
+
+/**
+ * Renders Acceleo debug elements.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class AcceleoModelPresentation extends LabelProvider implements IDebugModelPresentation {
+
+ /**
+ * Unique identifier for the Acceleo debug model.
+ */
+ public static final String ID_ACCELEO_DEBUG_MODEL = "org.eclipse.acceleo.ide.ui.debug.model.AcceleoModelPresentation"; //$NON-NLS-1$
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.ui.IDebugModelPresentation#setAttribute(java.lang.String, java.lang.Object)
+ */
+ public void setAttribute(String attribute, Object value) {
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.jface.viewers.LabelProvider#getImage(java.lang.Object)
+ */
+ public Image getImage(Object element) {
+ Image result;
+ if (element instanceof AcceleoVariable) {
+ try {
+ result = ((AcceleoValue)((AcceleoVariable)element).getValue()).getImage(element);
+ } catch (DebugException e) {
+ result = null;
+ AcceleoUIActivator.getDefault().getLog().log(e.getStatus());
+ }
+ } else if (element instanceof AcceleoLineBreakpoint) {
+ boolean isEnabled;
+ try {
+ isEnabled = ((AcceleoLineBreakpoint)element).isEnabled();
+ } catch (CoreException e) {
+ isEnabled = true;
+ }
+ ASTFragment astFragment = ((AcceleoLineBreakpoint)element).getASTFragment();
+ if (isEnabled && astFragment != null && astFragment.getEObjectNameFilter() != null
+ && astFragment.getEObjectNameFilter().length() > 0) {
+ result = AcceleoUIActivator.getDefault().getImage("icons/debug/filteredBrkp.gif"); //$NON-NLS-1$
+ } else {
+ result = null;
+ }
+ } else {
+ result = null;
+ }
+ return result;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object)
+ */
+ public String getText(Object element) {
+ String vRet = AcceleoUIMessages.getString("AcceleoModelPresentation.ElementText"); //$NON-NLS-1$
+ if (element instanceof AcceleoLineBreakpoint) {
+ AcceleoLineBreakpoint breakPoint = (AcceleoLineBreakpoint)element;
+ try {
+ String filePath;
+ if (breakPoint.getFile() == null) {
+ filePath = ""; //$NON-NLS-1$
+ } else {
+ filePath = breakPoint.getFile().getAbsolutePath();
+ }
+ if (filePath.lastIndexOf(File.separatorChar) != -1) {
+ filePath = filePath.substring(filePath.lastIndexOf(File.separatorChar) + 1);
+ }
+ vRet = AcceleoUIMessages
+ .getString(
+ "AcceleoModelPresentation.BreakpointText", new Object[] {filePath, Integer.toString(breakPoint.getLineNumber()),}); //$NON-NLS-1$
+ } catch (CoreException e) {
+ AcceleoUIActivator.getDefault().getLog().log(e.getStatus());
+ }
+ } else if (element instanceof IProcess) {
+ vRet = AcceleoUIMessages.getString("AcceleoModelPresentation.ProcessText"); //$NON-NLS-1$
+ } else if (element instanceof IThread) {
+ vRet = AcceleoUIMessages.getString("AcceleoModelPresentation.ThreadText"); //$NON-NLS-1$
+ } else if (element instanceof IDebugTarget) {
+ vRet = AcceleoUIMessages.getString("AcceleoModelPresentation.TargetText"); //$NON-NLS-1$
+ } else if (element instanceof AcceleoStackFrame) {
+ AcceleoStackFrame stackFrame = (AcceleoStackFrame)element;
+ try {
+ String sourceName = stackFrame.getSourceName();
+ if (sourceName != null && sourceName.length() > 0) {
+ vRet = sourceName + ' ' + (stackFrame.getLineNumber());
+ }
+ } catch (DebugException e) {
+ AcceleoUIActivator.getDefault().getLog().log(e.getStatus());
+ }
+ }
+ return vRet;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.ui.IDebugModelPresentation#computeDetail(org.eclipse.debug.core.model.IValue,
+ * org.eclipse.debug.ui.IValueDetailListener)
+ */
+ public void computeDetail(IValue value, IValueDetailListener listener) {
+ String detail = ""; //$NON-NLS-1$
+ try {
+ detail = value.getValueString();
+ } catch (DebugException e) {
+ // continue
+ }
+ listener.detailComputed(value, detail);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.ui.ISourcePresentation#getEditorInput(java.lang.Object)
+ */
+ public IEditorInput getEditorInput(Object element) {
+ IEditorInput result;
+ if (element instanceof File) {
+ IFile workspaceFile = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(
+ new Path(((File)element).getAbsolutePath()));
+ if (workspaceFile != null && workspaceFile.isAccessible()) {
+ result = new FileEditorInput(workspaceFile);
+ } else {
+ result = null;
+ }
+
+ } else if (element instanceof IFile) {
+ result = new FileEditorInput((IFile)element);
+ } else if (element instanceof ILineBreakpoint) {
+ result = new FileEditorInput((IFile)((ILineBreakpoint)element).getMarker().getResource());
+ } else {
+ result = null;
+ }
+ return result;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.ui.ISourcePresentation#getEditorId(org.eclipse.ui.IEditorInput,
+ * java.lang.Object)
+ */
+ public String getEditorId(IEditorInput input, Object element) {
+ String name;
+ if (element instanceof File) {
+ name = ((File)element).getName();
+ } else if (element instanceof IFile) {
+ name = ((IFile)element).getName();
+ } else if (element instanceof ILineBreakpoint) {
+ name = ((IFile)((ILineBreakpoint)element).getMarker().getResource()).getName();
+ } else {
+ name = ""; //$NON-NLS-1$
+ }
+ if (name.endsWith("." + IAcceleoConstants.MTL_FILE_EXTENSION)) { //$NON-NLS-1$
+ return AcceleoEditor.ACCELEO_EDITOR_ID;
+ } else {
+ return null;
+ }
+ }
+
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoProcess.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoProcess.java
new file mode 100644
index 0000000..b18049c
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoProcess.java
@@ -0,0 +1,136 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.debug.model;
+
+import org.eclipse.acceleo.internal.ide.ui.AcceleoUIMessages;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.model.IDebugTarget;
+import org.eclipse.debug.core.model.IProcess;
+import org.eclipse.debug.core.model.IStreamsProxy;
+
+/**
+ * The process of the debug target.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class AcceleoProcess extends AbstractDebugElement implements IProcess {
+
+ /**
+ * Constructor.
+ *
+ * @param target
+ * is the debug target
+ */
+ public AcceleoProcess(IDebugTarget target) {
+ super(target);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IProcess#getAttribute(java.lang.String)
+ */
+ public String getAttribute(String key) {
+ return getDebugTarget().getLaunch().getAttribute(key);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IProcess#getExitValue()
+ */
+ public int getExitValue() throws DebugException {
+ return 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IProcess#getLabel()
+ */
+ public String getLabel() {
+ return AcceleoUIMessages.getString("AcceleoProcess.Label"); //$NON-NLS-1$
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.acceleo.ide.ui.debug.model.AbstractDebugElement#getLaunch()
+ */
+ public ILaunch getLaunch() {
+ return getDebugTarget().getLaunch();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IProcess#getStreamsProxy()
+ */
+ public IStreamsProxy getStreamsProxy() {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IProcess#setAttribute(java.lang.String, java.lang.String)
+ */
+ public void setAttribute(String key, String value) {
+ getDebugTarget().getLaunch().setAttribute(key, value);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.acceleo.ide.ui.debug.model.AbstractDebugElement#getAdapter(java.lang.Class)
+ */
+ @SuppressWarnings("unchecked")
+ public Object getAdapter(Class adapter) {
+ Object ret = null;
+ if (adapter.equals(IProcess.class)) {
+ ret = this;
+ } else if (adapter.equals(IDebugTarget.class)) {
+ ret = getLaunch().getDebugTarget();
+ } else if (adapter.equals(ILaunch.class)) {
+ ret = getLaunch();
+ }
+ return ret;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.ITerminate#canTerminate()
+ */
+ public boolean canTerminate() {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.ITerminate#isTerminated()
+ */
+ public boolean isTerminated() {
+ return getDebugTarget().isTerminated();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.ITerminate#terminate()
+ */
+ public void terminate() throws DebugException {
+ getDebugTarget().terminate();
+ }
+
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoRunToLineAdapter.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoRunToLineAdapter.java
new file mode 100644
index 0000000..e2fdab6
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoRunToLineAdapter.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.debug.model;
+
+import org.eclipse.acceleo.internal.ide.ui.editors.template.AcceleoEditor;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.debug.core.model.IBreakpoint;
+import org.eclipse.debug.core.model.IDebugElement;
+import org.eclipse.debug.core.model.IDebugTarget;
+import org.eclipse.debug.core.model.ISuspendResume;
+import org.eclipse.debug.ui.actions.IRunToLineTarget;
+import org.eclipse.debug.ui.actions.RunToLineHandler;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ocl.utilities.ASTNode;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+/**
+ * Run to line target for the Acceleo debugger. An adapter for a "run to line" operation.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class AcceleoRunToLineAdapter implements IRunToLineTarget {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.ui.actions.IRunToLineTarget#runToLine(org.eclipse.ui.IWorkbenchPart,
+ * org.eclipse.jface.viewers.ISelection, org.eclipse.debug.core.model.ISuspendResume)
+ */
+ public void runToLine(IWorkbenchPart part, ISelection selection, ISuspendResume target)
+ throws CoreException {
+ IEditorPart editorPart = (IEditorPart)part;
+ ITextEditor textEditor = (ITextEditor)editorPart;
+ ITextSelection textSelection = (ITextSelection)selection;
+ int lineNumber = textSelection.getStartLine() + 1;
+ int offset = textSelection.getOffset();
+ int length = textSelection.getLength();
+ if (lineNumber > 0 && textEditor instanceof AcceleoEditor && target instanceof IAdaptable) {
+ IDebugTarget debugTarget = (IDebugTarget)((IAdaptable)target).getAdapter(IDebugTarget.class);
+ if (debugTarget != null) {
+ ASTNode astNode = AcceleoLineBreakpointAdapter.getBreakpointASTNodeAt(((AcceleoEditor)textEditor)
+ .getContent(), offset);
+ if (astNode != null) {
+ IFile resource = (IFile)textEditor.getEditorInput().getAdapter(IResource.class);
+ IBreakpoint breakpoint = new AcceleoRunToLineBreakpoint(astNode, resource, lineNumber,
+ offset, length);
+ RunToLineHandler handler = new RunToLineHandler(debugTarget, target, breakpoint);
+ handler.run(new NullProgressMonitor());
+ }
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.ui.actions.IRunToLineTarget#canRunToLine(org.eclipse.ui.IWorkbenchPart,
+ * org.eclipse.jface.viewers.ISelection, org.eclipse.debug.core.model.ISuspendResume)
+ */
+ public boolean canRunToLine(IWorkbenchPart part, ISelection selection, ISuspendResume target) {
+ return target instanceof IDebugElement
+ && ((IDebugElement)target).getModelIdentifier().equals(
+ AcceleoModelPresentation.ID_ACCELEO_DEBUG_MODEL);
+ }
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoRunToLineBreakpoint.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoRunToLineBreakpoint.java
new file mode 100644
index 0000000..6eb7f31
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoRunToLineBreakpoint.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.debug.model;
+
+import org.eclipse.acceleo.engine.internal.debug.ASTFragment;
+import org.eclipse.acceleo.internal.ide.ui.AcceleoUIMessages;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.model.IBreakpoint;
+import org.eclipse.emf.ecore.EObject;
+
+/**
+ * A run to line breakpoint. The breakpoint for a "run to line" operation.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class AcceleoRunToLineBreakpoint extends AcceleoLineBreakpoint {
+
+ /**
+ * Constructs a run-to-line breakpoint in the given Acceleo file.
+ *
+ * @param astNode
+ * is the AST node to associate with the breakpoint.
+ * @param resource
+ * file on which to set the breakpoint
+ * @param lineNumber
+ * 1-based line number of the breakpoint
+ * @param offset
+ * offset of the breakpoint
+ * @param length
+ * length of the breakpoint
+ * @exception DebugException
+ * if unable to create the breakpoint
+ */
+ public AcceleoRunToLineBreakpoint(final EObject astNode, final IFile resource, final int lineNumber,
+ final int offset, final int length) throws DebugException {
+ IWorkspaceRunnable runnable = new IWorkspaceRunnable() {
+ public void run(IProgressMonitor monitor) throws CoreException {
+ IMarker marker = ResourcesPlugin.getWorkspace().getRoot().createMarker(MARKER_ID);
+ setMarker(marker);
+ marker.setAttribute(IBreakpoint.ENABLED, Boolean.TRUE);
+ marker.setAttribute(IMarker.LINE_NUMBER, lineNumber);
+ marker.setAttribute(IBreakpoint.ID, getModelIdentifier());
+ marker.setAttribute(IMarker.CHAR_START, offset);
+ marker.setAttribute(IMarker.CHAR_END, offset + length);
+ marker.setAttribute(AST_FRAGMENT, new ASTFragment(astNode).toString());
+ marker
+ .setAttribute(
+ IMarker.MESSAGE,
+ AcceleoUIMessages
+ .getString(
+ "AcceleoLineBreakpoint.HoverText", new Object[] {astNode.eClass().getName(), resource.getName(), Integer.toString(lineNumber),})); //$NON-NLS-1$
+ setRegistered(false);
+ }
+ };
+ run(getMarkerRule(resource), runnable);
+ }
+
+ /**
+ * Returns whether this breakpoint is a run-to-line breakpoint.
+ *
+ * @return whether this breakpoint is a run-to-line breakpoint
+ */
+ public boolean isRunToLineBreakpoint() {
+ return true;
+ }
+
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoStackFrame.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoStackFrame.java
new file mode 100644
index 0000000..d79048e
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoStackFrame.java
@@ -0,0 +1,327 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.debug.model;
+
+import java.util.Iterator;
+
+import org.eclipse.acceleo.internal.ide.ui.debug.core.StackInfo;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.model.IRegisterGroup;
+import org.eclipse.debug.core.model.IStackFrame;
+import org.eclipse.debug.core.model.IThread;
+import org.eclipse.debug.core.model.IVariable;
+
+/**
+ * The Acceleo stack frame. A stack frame represents an execution context in a suspended thread. A stack frame
+ * contains variables representing visible locals and arguments at the current execution location.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class AcceleoStackFrame extends AbstractDebugElement implements IStackFrame {
+
+ /**
+ * The current Acceleo thread.
+ */
+ private IThread thread;
+
+ /**
+ * Current data of the debugger execution stack. The debugger stack is shown in the "Launch View".
+ */
+ private StackInfo stackInfo;
+
+ /**
+ * Constructor. It constructs a stack frame in the given thread with the given frame data.
+ *
+ * @param thread
+ * the Acceleo thread
+ * @param aStackInfo
+ * the current data of the debugger execution stack
+ */
+ public AcceleoStackFrame(IThread thread, StackInfo aStackInfo) {
+ super(thread.getDebugTarget());
+ this.thread = thread;
+ stackInfo = aStackInfo;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IStackFrame#getThread()
+ */
+ public IThread getThread() {
+ return thread;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IStackFrame#getVariables()
+ */
+ public IVariable[] getVariables() throws DebugException {
+ IVariable[] ret = new AcceleoVariable[stackInfo.getVariables().keySet().size()];
+ int i = 0;
+ for (Iterator<String> iterator = stackInfo.getVariables().keySet().iterator(); iterator.hasNext();) {
+ String name = iterator.next();
+ Object value = (Object)stackInfo.getVariables().get(name);
+ ret[i] = new AcceleoVariable(this, name, value, AcceleoVariable.DEFAULT_TYPE);
+ ++i;
+ }
+ return ret;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IStackFrame#hasVariables()
+ */
+ public boolean hasVariables() throws DebugException {
+ return getVariables().length > 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IStackFrame#getLineNumber()
+ */
+ public int getLineNumber() throws DebugException {
+ return stackInfo.getLine();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IStackFrame#getCharStart()
+ */
+ public int getCharStart() throws DebugException {
+ return stackInfo.getCharStart();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IStackFrame#getCharEnd()
+ */
+ public int getCharEnd() throws DebugException {
+ return stackInfo.getCharEnd();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IStackFrame#getName()
+ */
+ public String getName() throws DebugException {
+ return stackInfo.getFile().getName();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IStackFrame#getRegisterGroups()
+ */
+ public IRegisterGroup[] getRegisterGroups() throws DebugException {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IStackFrame#hasRegisterGroups()
+ */
+ public boolean hasRegisterGroups() throws DebugException {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IStep#canStepInto()
+ */
+ public boolean canStepInto() {
+ return getThread().canStepInto();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IStep#canStepOver()
+ */
+ public boolean canStepOver() {
+ return getThread().canStepOver();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IStep#canStepReturn()
+ */
+ public boolean canStepReturn() {
+ return getThread().canStepReturn();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IStep#isStepping()
+ */
+ public boolean isStepping() {
+ return getThread().isStepping();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IStep#stepInto()
+ */
+ public void stepInto() throws DebugException {
+ getThread().stepInto();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IStep#stepOver()
+ */
+ public void stepOver() throws DebugException {
+ getThread().stepOver();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IStep#stepReturn()
+ */
+ public void stepReturn() throws DebugException {
+ getThread().stepReturn();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.ISuspendResume#canResume()
+ */
+ public boolean canResume() {
+ return getThread().canResume();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.ISuspendResume#canSuspend()
+ */
+ public boolean canSuspend() {
+ return getThread().canSuspend();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.ISuspendResume#isSuspended()
+ */
+ public boolean isSuspended() {
+ return getThread().isSuspended();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.ISuspendResume#resume()
+ */
+ public void resume() throws DebugException {
+ getThread().resume();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.ISuspendResume#suspend()
+ */
+ public void suspend() throws DebugException {
+ getThread().suspend();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.ITerminate#canTerminate()
+ */
+ public boolean canTerminate() {
+ return getThread().canTerminate();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.ITerminate#isTerminated()
+ */
+ public boolean isTerminated() {
+ return getThread().isTerminated();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.ITerminate#terminate()
+ */
+ public void terminate() throws DebugException {
+ getThread().terminate();
+ }
+
+ /**
+ * Returns the name of the source file this stack frame is associated with.
+ *
+ * @return the name of the source file this stack frame is associated with
+ */
+ public String getSourceName() {
+ if (stackInfo != null && stackInfo.getFile() != null) {
+ return stackInfo.getFile().getName();
+ } else {
+ return ""; //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals(Object obj) {
+ if (obj instanceof AcceleoStackFrame) {
+ AcceleoStackFrame sf = (AcceleoStackFrame)obj;
+ try {
+ return sf.getSourceName().equals(getSourceName()) && sf.getLineNumber() == getLineNumber()
+ && sf.getCharStart() == getCharStart() && sf.getCharEnd() == getCharEnd();
+ } catch (DebugException e) {
+ // continue
+ }
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ public int hashCode() {
+ return getSourceName().hashCode();
+ }
+
+ /**
+ * Returns the debugger execution context. It means the current data of the debugger execution stack.
+ *
+ * @return the debugger execution context
+ */
+ public StackInfo getStackInfo() {
+ return stackInfo;
+ }
+
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoThread.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoThread.java
new file mode 100644
index 0000000..aea6d9b
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoThread.java
@@ -0,0 +1,285 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.debug.model;
+
+import org.eclipse.acceleo.internal.ide.ui.debug.core.ITemplateDebugger;
+import org.eclipse.acceleo.internal.ide.ui.debug.core.StackInfo;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.model.IBreakpoint;
+import org.eclipse.debug.core.model.IStackFrame;
+import org.eclipse.debug.core.model.IThread;
+
+/**
+ * An Acceleo thread that works like a VM for an Acceleo application. The Acceleo VM is single threaded.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class AcceleoThread extends AbstractDebugElement implements IThread {
+
+ /**
+ * Breakpoints this thread is suspended at or <code>null</code> if none.
+ */
+ private IBreakpoint[] fBreakpoints;
+
+ /**
+ * Whether this thread is stepping.
+ */
+ private boolean fStepping;
+
+ /**
+ * Whether this thread is suspended.
+ */
+ private boolean suspended;
+
+ /**
+ * Constructor. It constructs a new thread for the given debug target.
+ *
+ * @param target
+ * is the debug target
+ */
+ public AcceleoThread(AcceleoDebugTarget target) {
+ super(target);
+ }
+
+ /**
+ * Sets whether this thread is stepping.
+ *
+ * @param stepping
+ * indicates whether this thread is stepping
+ */
+ protected void setStepping(boolean stepping) {
+ fStepping = stepping;
+ }
+
+ /**
+ * Sets whether this thread is suspended.
+ *
+ * @param suspended
+ * whether this thread is suspended
+ */
+ protected void setSuspended(boolean suspended) {
+ this.suspended = suspended;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IThread#getStackFrames()
+ */
+ public IStackFrame[] getStackFrames() throws DebugException {
+ AcceleoDebugTarget debugTarget = (AcceleoDebugTarget)getDebugTarget();
+ ITemplateDebugger debugger = debugTarget.getDebugger();
+ StackInfo[] stack = debugger.getStack();
+ IStackFrame[] ret = new IStackFrame[stack.length];
+ for (int i = 0; i < ret.length; ++i) {
+ ret[i] = new AcceleoStackFrame(this, stack[stack.length - i - 1]);
+ }
+ return ret;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IThread#hasStackFrames()
+ */
+ public boolean hasStackFrames() throws DebugException {
+ return isSuspended();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IThread#getPriority()
+ */
+ public int getPriority() throws DebugException {
+ return 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IThread#getTopStackFrame()
+ */
+ public IStackFrame getTopStackFrame() throws DebugException {
+ IStackFrame[] frames = getStackFrames();
+ if (frames.length > 0) {
+ return frames[0];
+ }
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IThread#getName()
+ */
+ public String getName() throws DebugException {
+ return "Thread[1]"; //$NON-NLS-1$
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IThread#getBreakpoints()
+ */
+ public IBreakpoint[] getBreakpoints() {
+ if (fBreakpoints == null) {
+ return new IBreakpoint[0];
+ }
+ return fBreakpoints;
+ }
+
+ /**
+ * Sets the breakpoints this thread is suspended at, or <code>null</code> if none.
+ *
+ * @param breakpoints
+ * the breakpoints this thread is suspended at, or <code>null</code> if none
+ */
+ protected void setBreakpoints(IBreakpoint[] breakpoints) {
+ fBreakpoints = breakpoints;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.ISuspendResume#canResume()
+ */
+ public boolean canResume() {
+ return isSuspended();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.ISuspendResume#canSuspend()
+ */
+ public boolean canSuspend() {
+ return !isSuspended();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.ISuspendResume#isSuspended()
+ */
+ public boolean isSuspended() {
+ return suspended;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.ISuspendResume#resume()
+ */
+ public void resume() throws DebugException {
+ getDebugTarget().resume();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.ISuspendResume#suspend()
+ */
+ public void suspend() throws DebugException {
+ getDebugTarget().suspend();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IStep#canStepInto()
+ */
+ public boolean canStepInto() {
+ return isSuspended();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IStep#canStepOver()
+ */
+ public boolean canStepOver() {
+ return isSuspended();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IStep#canStepReturn()
+ */
+ public boolean canStepReturn() {
+ return isSuspended();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IStep#isStepping()
+ */
+ public boolean isStepping() {
+ return fStepping;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IStep#stepInto()
+ */
+ public void stepInto() throws DebugException {
+ ((AcceleoDebugTarget)getDebugTarget()).stepInto();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IStep#stepOver()
+ */
+ public void stepOver() throws DebugException {
+ ((AcceleoDebugTarget)getDebugTarget()).stepOver();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IStep#stepReturn()
+ */
+ public void stepReturn() throws DebugException {
+ ((AcceleoDebugTarget)getDebugTarget()).stepReturn();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.ITerminate#canTerminate()
+ */
+ public boolean canTerminate() {
+ return !isTerminated();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.ITerminate#isTerminated()
+ */
+ public boolean isTerminated() {
+ return getDebugTarget().isTerminated();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.ITerminate#terminate()
+ */
+ public void terminate() throws DebugException {
+ getDebugTarget().terminate();
+ }
+
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoValue.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoValue.java
new file mode 100644
index 0000000..dd61281
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoValue.java
@@ -0,0 +1,327 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.debug.model;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.eclipse.acceleo.ide.ui.AcceleoUIActivator;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.model.IDebugTarget;
+import org.eclipse.debug.core.model.IValue;
+import org.eclipse.debug.core.model.IVariable;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * An Acceleo value represents the value of an Acceleo variable. It is shown in the Variables view.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class AcceleoValue extends AbstractDebugElement implements IValue {
+
+ /**
+ * The real value.
+ */
+ private Object value;
+
+ /**
+ * The type of this Acceleo value.
+ */
+ private int type;
+
+ /**
+ * Constructor.
+ *
+ * @param target
+ * is the debug target
+ * @param value
+ * is the real value
+ * @param type
+ * is the type of the value
+ */
+ public AcceleoValue(IDebugTarget target, Object value, int type) {
+ super(target);
+ this.value = value;
+ this.type = type;
+ }
+
+ /**
+ * Returns an image for the element, or null if a default image should be used.
+ *
+ * @param element
+ * is the element
+ * @return an image or null
+ * @throws DebugException
+ * when an issue occurs
+ */
+ public Image getImage(Object element) throws DebugException {
+ Image ret = null;
+ if (type == AcceleoVariable.CLASS_TYPE) {
+ ret = AcceleoUIActivator.getDefault().getImage("icons/debug/class.gif"); //$NON-NLS-1$
+ } else if (type == AcceleoVariable.ATTRIBUTE_TYPE) {
+ ret = AcceleoUIActivator.getDefault().getImage("icons/debug/attribute.gif"); //$NON-NLS-1$
+ } else if (type == AcceleoVariable.REFERENCE_TYPE) {
+ ret = AcceleoUIActivator.getDefault().getImage("icons/debug/reference.gif"); //$NON-NLS-1$
+ } else {
+ if (value instanceof Boolean) {
+ ret = AcceleoUIActivator.getDefault().getImage("icons/debug/boolean.gif"); //$NON-NLS-1$
+ } else if (value instanceof Double) {
+ ret = AcceleoUIActivator.getDefault().getImage("icons/debug/double.gif"); //$NON-NLS-1$
+ } else if (value instanceof EObject) {
+ ret = AcceleoUIActivator.getDefault().getImage("icons/debug/class.gif"); //$NON-NLS-1$
+ } else if (value instanceof Integer) {
+ ret = AcceleoUIActivator.getDefault().getImage("icons/debug/int.gif"); //$NON-NLS-1$
+ } else if (value instanceof String) {
+ ret = AcceleoUIActivator.getDefault().getImage("icons/debug/string.gif"); //$NON-NLS-1$
+ } else if (value instanceof List) {
+ ret = AcceleoUIActivator.getDefault().getImage("icons/debug/list.gif"); //$NON-NLS-1$
+ } else if (value == null) {
+ ret = AcceleoUIActivator.getDefault().getImage("icons/debug/null.gif"); //$NON-NLS-1$
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IValue#getReferenceTypeName()
+ */
+ public String getReferenceTypeName() throws DebugException {
+ String ret = ""; //$NON-NLS-1$
+ if (value != null) {
+ if (value instanceof EObject) {
+ ret = ((EObject)value).eClass().getName();
+ } else {
+ ret = value.getClass().getName().substring(value.getClass().getName().lastIndexOf('.') + 1);
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IValue#getValueString()
+ */
+ public String getValueString() throws DebugException {
+ String ret = ""; //$NON-NLS-1$
+ if (value != null) {
+ if (value instanceof EObject) {
+ EObject eObject = (EObject)value;
+ ret = getEObjectValue(eObject);
+ } else if (value instanceof Collection) {
+ ret = toSimpleString((Collection<?>)value);
+ } else {
+ ret = value.toString();
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IValue#isAllocated()
+ */
+ public boolean isAllocated() throws DebugException {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IValue#getVariables()
+ */
+ public IVariable[] getVariables() throws DebugException {
+ IVariable[] ret = null;
+ if (value != null) {
+ if (value instanceof EObject) {
+ ret = this.computeEObjectVariables((EObject)value);
+ } else if (value instanceof Collection) {
+ ret = this.computeCollectionVariables((Collection<?>)value);
+ } else {
+ ret = this.computeVariables(value);
+ }
+ } else {
+ ret = new IVariable[0];
+ }
+ return ret;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IValue#hasVariables()
+ */
+ public boolean hasVariables() throws DebugException {
+ return getVariables().length > 0;
+ }
+
+ /**
+ * Computes the variables for an EObject.
+ *
+ * @param object
+ * the EObject
+ * @return the variables
+ */
+ private IVariable[] computeEObjectVariables(EObject object) {
+ List<IVariable> variables = new LinkedList<IVariable>();
+ List<EStructuralFeature> structuralFeatures = object.eClass().getEAllStructuralFeatures();
+ for (Iterator<EStructuralFeature> iterFeatures = structuralFeatures.iterator(); iterFeatures
+ .hasNext();) {
+ EStructuralFeature currentFeature = iterFeatures.next();
+ String featureName = currentFeature.getName();
+ Object featureValue = object.eGet(currentFeature);
+ int referenceType;
+ if (currentFeature instanceof EReference) {
+ referenceType = AcceleoVariable.REFERENCE_TYPE;
+ } else {
+ referenceType = AcceleoVariable.ATTRIBUTE_TYPE;
+ }
+ if ((featureValue instanceof Collection && ((Collection<?>)featureValue).size() > 0)
+ || (!(featureValue instanceof Collection) && featureValue != null)) {
+ variables.add(new AcceleoVariable(getDebugTarget(), featureName, featureValue, referenceType));
+ }
+ }
+ return variables.toArray(new IVariable[variables.size()]);
+ }
+
+ /**
+ * Computes the variables for a collection.
+ *
+ * @param collection
+ * the collection
+ * @return the variables
+ * @throws DebugException
+ * when an issue occurs
+ */
+ private IVariable[] computeCollectionVariables(Collection<?> collection) throws DebugException {
+ List<IVariable> variables = new LinkedList<IVariable>();
+ for (Iterator<?> iterObjects = collection.iterator(); iterObjects.hasNext();) {
+ Object element = iterObjects.next();
+ if (element instanceof EObject) {
+ variables.add(this.eObjectToVariable((EObject)element));
+ } else if (element instanceof Collection) {
+ variables.add(new AcceleoVariable(getDebugTarget(), toSimpleString((Collection<?>)element),
+ element, AcceleoVariable.DEFAULT_TYPE));
+ } else {
+ variables.add(new AcceleoVariable(getDebugTarget(),
+ "" + element, element, AcceleoVariable.DEFAULT_TYPE)); //$NON-NLS-1$
+ }
+ }
+ return variables.toArray(new IVariable[variables.size()]);
+ }
+
+ /**
+ * Computes the variables for an object.
+ *
+ * @param object
+ * the object
+ * @return an empty array
+ */
+ private IVariable[] computeVariables(Object object) {
+ List<IVariable> variables = new LinkedList<IVariable>();
+ return variables.toArray(new IVariable[variables.size()]);
+ }
+
+ /**
+ * Transforms an EObject into a variable.
+ *
+ * @param eObject
+ * the EObject to transform
+ * @return the new variable
+ */
+ private IVariable eObjectToVariable(EObject eObject) {
+ String variableName = eObject.eClass().getName();
+ return new AcceleoVariable(getDebugTarget(), variableName, eObject, AcceleoVariable.CLASS_TYPE);
+ }
+
+ /**
+ * Returns a value representing the given EObject.
+ *
+ * @param eObject
+ * the EObject
+ * @return a value representing the given EObject
+ */
+ private String getEObjectValue(EObject eObject) {
+ String variableName = eObject.eClass().getName();
+ EStructuralFeature feature = eObject.eClass().getEStructuralFeature("name"); //$NON-NLS-1$
+ if (feature != null) {
+ Object variableNameObject = eObject.eGet(feature);
+ String variableValue;
+ if (variableNameObject != null) {
+ variableValue = variableNameObject.toString();
+ } else {
+ variableValue = ""; //$NON-NLS-1$
+ }
+ variableName = variableName + ':' + variableValue;
+ }
+ return variableName;
+ }
+
+ /**
+ * Transforms a collection into a string.
+ *
+ * @param collection
+ * the collection
+ * @return the string
+ */
+ private String toSimpleString(Collection<?> collection) {
+ List<String> strings = new ArrayList<String>(collection.size());
+ Iterator<?> iterValues = collection.iterator();
+ while (iterValues.hasNext()) {
+ Object currentValue = iterValues.next();
+ if (currentValue instanceof EObject) {
+ EObject eObject = (EObject)currentValue;
+ String typeName = eObject.eClass().getName();
+ String label = ""; //$NON-NLS-1$
+ EStructuralFeature structuralFeature = eObject.eClass().getEStructuralFeature("name"); //$NON-NLS-1$
+ if (structuralFeature != null) {
+ Object nameObject = eObject.eGet(structuralFeature);
+ if (nameObject != null) {
+ label = nameObject.toString();
+ } else {
+ label = ""; //$NON-NLS-1$
+ }
+ }
+ strings.add(typeName + ':' + label);
+ } else if (currentValue instanceof Collection) {
+ strings.add("Collection"); //$NON-NLS-1$
+ } else {
+ String typeName = currentValue.getClass().getName().substring(
+ currentValue.getClass().getName().lastIndexOf('.') + 1);
+ String label;
+ label = currentValue.toString();
+ strings.add(typeName + ':' + label);
+ }
+ }
+ StringBuffer buffer = new StringBuffer("["); //$NON-NLS-1$
+ Iterator<String> iterStrings = strings.iterator();
+ boolean first = true;
+ while (iterStrings.hasNext()) {
+ if (first) {
+ first = false;
+ } else {
+ buffer.append(", "); //$NON-NLS-1$
+ }
+ buffer.append(iterStrings.next());
+ }
+ buffer.append(']');
+ return buffer.toString();
+ }
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoVariable.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoVariable.java
new file mode 100644
index 0000000..4324d93
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/debug/model/AcceleoVariable.java
@@ -0,0 +1,208 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.debug.model;
+
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.model.IDebugTarget;
+import org.eclipse.debug.core.model.IValue;
+import org.eclipse.debug.core.model.IVariable;
+
+/**
+ * An Acceleo variable in a variable of an Acceleo Stack Frame. They are shown in the Variables view.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class AcceleoVariable extends AbstractDebugElement implements IVariable, Comparable<AcceleoVariable> {
+
+ /**
+ * The default type.
+ */
+ protected static final int DEFAULT_TYPE = 0;
+
+ /**
+ * The class type.
+ */
+ protected static final int CLASS_TYPE = 1;
+
+ /**
+ * The reference type.
+ */
+ protected static final int REFERENCE_TYPE = 2;
+
+ /**
+ * The attribute type.
+ */
+ protected static final int ATTRIBUTE_TYPE = 3;
+
+ /**
+ * The name of the variable.
+ */
+ private String name;
+
+ /**
+ * The real value.
+ */
+ private Object value;
+
+ /**
+ * The type of this Acceleo value. The default type is DEFAULT_TYPE.
+ */
+ private int type;
+
+ /**
+ * Constructor. It constructs a variable contained in the given stack frame with the given name.
+ *
+ * @param frame
+ * is the owning stack frame
+ * @param name
+ * is the variable name
+ * @param aValue
+ * is the value
+ * @param type
+ * is the type of the variable
+ */
+ public AcceleoVariable(AcceleoStackFrame frame, String name, Object aValue, int type) {
+ this(frame.getDebugTarget(), name, aValue, type);
+ }
+
+ /**
+ * Constructor. It constructs a variable contained in the given debug target with the given name.
+ *
+ * @param aDebugTarget
+ * is the debug target
+ * @param name
+ * is the variable name
+ * @param aValue
+ * is the value
+ * @param type
+ * is the type of the variable
+ */
+ public AcceleoVariable(IDebugTarget aDebugTarget, String name, Object aValue, int type) {
+ super(aDebugTarget);
+ this.name = name;
+ this.value = aValue;
+ this.type = type;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IVariable#getValue()
+ */
+ public IValue getValue() throws DebugException {
+ return new AcceleoValue(getDebugTarget(), value, type);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IVariable#getName()
+ */
+ public String getName() throws DebugException {
+ return name;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IVariable#getReferenceTypeName()
+ */
+ public String getReferenceTypeName() throws DebugException {
+ String ret = ""; //$NON-NLS-1$
+ if (value != null) {
+ ret = getSimpleName(value.getClass());
+ }
+ return ret;
+ }
+
+ /**
+ * Gets the simple name of the given class. As an example, 'String' is the simple name of the class
+ * 'java.lang.String'.
+ *
+ * @param c
+ * is a class
+ * @return the simple name of the class
+ */
+ private String getSimpleName(Class<?> c) {
+ String cName = c.getName();
+ int i = cName.lastIndexOf("."); //$NON-NLS-1$
+ if (i > -1) {
+ cName = cName.substring(i + 1);
+ }
+ return cName;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IVariable#hasValueChanged()
+ */
+ public boolean hasValueChanged() throws DebugException {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IValueModification#setValue(java.lang.String)
+ */
+ public void setValue(String expression) throws DebugException {
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IValueModification#setValue(org.eclipse.debug.core.model.IValue)
+ */
+ public void setValue(IValue value) throws DebugException {
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IValueModification#supportsValueModification()
+ */
+ public boolean supportsValueModification() {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IValueModification#verifyValue(java.lang.String)
+ */
+ public boolean verifyValue(String expression) throws DebugException {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.debug.core.model.IValueModification#verifyValue(org.eclipse.debug.core.model.IValue)
+ */
+ public boolean verifyValue(IValue aValue) throws DebugException {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Comparable#compareTo(java.lang.Object)
+ */
+ public int compareTo(AcceleoVariable arg0) {
+ int ret = 0;
+ if (arg0.name != null && name != null) {
+ ret = name.compareTo(arg0.name);
+ }
+ return ret;
+ }
+
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoCompletionChoice.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoCompletionChoice.java
new file mode 100644
index 0000000..2a50670
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoCompletionChoice.java
@@ -0,0 +1,123 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.editors.template;
+
+import org.eclipse.acceleo.model.mtl.ModuleElement;
+import org.eclipse.ocl.helper.Choice;
+import org.eclipse.ocl.helper.ChoiceKind;
+
+/**
+ * Description of an Acceleo syntax completion choice. An Acceleo choice is based on an OCL choice. The choice also
+ * can provide the actual Acceleo model element that it represents.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class AcceleoCompletionChoice implements Choice {
+
+ /**
+ * The OCL choice.
+ */
+ private Choice oclChoice;
+
+ /**
+ * The Acceleo element.
+ */
+ private ModuleElement acceleoElement;
+
+ /**
+ * Constructor.
+ *
+ * @param oclChoice
+ * the OCL choice
+ * @param acceleoElement
+ * the Acceleo element
+ */
+ AcceleoCompletionChoice(Choice oclChoice, ModuleElement acceleoElement) {
+ this.oclChoice = oclChoice;
+ this.acceleoElement = acceleoElement;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.ocl.helper.Choice#getName()
+ */
+ public String getName() {
+ return oclChoice.getName();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.ocl.helper.Choice#getDescription()
+ */
+ public String getDescription() {
+ return oclChoice.getDescription();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.ocl.helper.Choice#getKind()
+ */
+ public ChoiceKind getKind() {
+ return oclChoice.getKind();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.ocl.helper.Choice#getElement()
+ */
+ public Object getElement() {
+ return oclChoice.getElement();
+ }
+
+ /**
+ * Gets the Acceleo element.
+ *
+ * @return the Acceleo element
+ */
+ public ModuleElement getAcceleoElement() {
+ return acceleoElement;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ public int hashCode() {
+ return oclChoice.hashCode();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals(Object obj) {
+ if (obj instanceof AcceleoCompletionChoice) {
+ return oclChoice.equals(((AcceleoCompletionChoice)obj).oclChoice);
+ } else {
+ return oclChoice.equals(obj);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ return oclChoice.toString();
+ }
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoCompletionProcessor.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoCompletionProcessor.java
new file mode 100644
index 0000000..99e0b59
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoCompletionProcessor.java
@@ -0,0 +1,1243 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.editors.template;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.eclipse.acceleo.common.IAcceleoConstants;
+import org.eclipse.acceleo.ide.ui.AcceleoUIActivator;
+import org.eclipse.acceleo.internal.parser.cst.utils.Sequence;
+import org.eclipse.acceleo.internal.parser.cst.utils.SequenceBlock;
+import org.eclipse.acceleo.parser.cst.Block;
+import org.eclipse.acceleo.parser.cst.CSTNode;
+import org.eclipse.acceleo.parser.cst.CstPackage;
+import org.eclipse.acceleo.parser.cst.IfBlock;
+import org.eclipse.acceleo.parser.cst.InitSection;
+import org.eclipse.acceleo.parser.cst.LetBlock;
+import org.eclipse.acceleo.parser.cst.ModelExpression;
+import org.eclipse.acceleo.parser.cst.Module;
+import org.eclipse.acceleo.parser.cst.ModuleElement;
+import org.eclipse.acceleo.parser.cst.ModuleExtendsValue;
+import org.eclipse.acceleo.parser.cst.ModuleImportsValue;
+import org.eclipse.acceleo.parser.cst.Query;
+import org.eclipse.acceleo.parser.cst.Template;
+import org.eclipse.acceleo.parser.cst.TemplateOverridesValue;
+import org.eclipse.acceleo.parser.cst.TextExpression;
+import org.eclipse.acceleo.parser.cst.TypedModel;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EClassifier;
+import org.eclipse.emf.ecore.EOperation;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EParameter;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.contentassist.CompletionProposal;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
+import org.eclipse.jface.text.contentassist.IContextInformation;
+import org.eclipse.jface.text.contentassist.IContextInformationValidator;
+import org.eclipse.ocl.helper.Choice;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * A completion processor for the Acceleo template editor.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class AcceleoCompletionProcessor implements IContentAssistProcessor {
+
+ /**
+ * The auto activation characters for completion proposal.
+ */
+ private static final char[] AUTO_ACTIVATION_CHARACTERS = new char[] {' ', '.', '[', '-', '>', ':'}; // Unless
+
+ /**
+ * The source content.
+ */
+ protected AcceleoSourceContent content;
+
+ /**
+ * The text used to compute the proposals.
+ */
+ private String text;
+
+ /**
+ * An offset within the text for which completions should be computed.
+ */
+ private int offset;
+
+ /**
+ * The CST node at the current offset.
+ */
+ private CSTNode cstNode;
+
+ /**
+ * The default type of the variables.
+ */
+ private String defaultVariableType;
+
+ /**
+ * Constructor.
+ *
+ * @param content
+ * is the content
+ */
+ public AcceleoCompletionProcessor(AcceleoSourceContent content) {
+ super();
+ this.content = content;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#computeCompletionProposals(org.eclipse.jface.text.ITextViewer,
+ * int)
+ */
+ public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int pos) {
+ if (viewer != null) {
+ text = viewer.getDocument().get();
+ ITextSelection selection = (ITextSelection)viewer.getSelectionProvider().getSelection();
+ if (selection != null && selection.getOffset() == pos) {
+ offset = selection.getOffset() + selection.getLength();
+ } else {
+ offset = pos;
+ }
+ } else {
+ text = content.getText();
+ offset = pos;
+ }
+ cstNode = content.getCSTNode(offset, offset);
+ if (cstNode instanceof InitSection && offset == cstNode.getStartPosition()
+ && cstNode.eContainer() != null) {
+ // We change the CSTNode if we are on the first index of an InitSection
+ cstNode = (CSTNode)cstNode.eContainer();
+ }
+ defaultVariableType = "EObject"; //$NON-NLS-1$
+ if (text.indexOf("http://www.eclipse.org/uml2/") > -1) { //$NON-NLS-1$
+ defaultVariableType = "Element"; //$NON-NLS-1$
+ }
+ try {
+ return computeCompletionProposals();
+ } finally {
+ text = null;
+ offset = 0;
+ cstNode = null;
+ }
+ }
+
+ /**
+ * Returns a list of completion proposals based on the specified location within the text.
+ *
+ * @return an array of completion proposals or null if no proposals are possible
+ */
+ private ICompletionProposal[] computeCompletionProposals() {
+ List<ICompletionProposal> proposals = new ArrayList<ICompletionProposal>();
+ if (cstNode == null
+ || (cstNode instanceof Module && cstNode.getEndPosition() == 0 && cstNode.getStartPosition() == 0)) {
+ computeModulePatternProposals(proposals);
+ } else if (cstNode instanceof TypedModel) {
+ computeEPackageProposals(proposals);
+ } else if (cstNode instanceof ModuleImportsValue || cstNode instanceof ModuleExtendsValue) {
+ computeImportProposals(proposals);
+ } else {
+ if (offset > 0 && text.charAt(offset - 1) != '/') {
+ computeEClassifierProposals(proposals);
+ if (proposals.size() == 0) {
+ computeKeywordsProposals(proposals);
+ if (!isNextSignificantChar(']')) {
+ computePatternsProposals(proposals);
+ }
+ }
+ if (text.charAt(offset - 1) != ']') {
+ if (cstNode instanceof ModelExpression || cstNode instanceof InitSection) {
+ computeOCLProposals(proposals);
+ } else if (cstNode instanceof Block && !(cstNode instanceof Template)) {
+ computeOCLProposals(proposals);
+ } else if (cstNode instanceof Query && cstNode.getStartPosition() > -1
+ && offset > cstNode.getStartPosition()
+ && isHeaderAfterParenthesis(text.substring(cstNode.getStartPosition(), offset))) {
+ computeOCLProposals(proposals);
+ } else if (cstNode instanceof TemplateOverridesValue) {
+ computeTemplatesProposals(proposals);
+ }
+ }
+ }
+ }
+ return proposals.toArray(new ICompletionProposal[proposals.size()]);
+ }
+
+ /**
+ * Indicates if the next significant character matches with the given one.
+ *
+ * @param ref
+ * is the character to match
+ * @return true if 'ref' is the next significant character
+ */
+ private boolean isNextSignificantChar(char ref) {
+ if (offset < text.length()) {
+ int i = offset;
+ char c;
+ do {
+ c = text.charAt(i);
+ i++;
+ } while (Character.isWhitespace(c) && i < text.length());
+ return c == ref;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Computes a list of templates completion proposals based on the specified location within the text.
+ *
+ * @param proposals
+ * are the completion proposals (in out parameter)
+ */
+ private void computeTemplatesProposals(List<ICompletionProposal> proposals) {
+ int i = offset;
+ while (i > 0 && Character.isLetterOrDigit(text.charAt(i - 1))) {
+ i--;
+ }
+ String start = text.substring(i, offset);
+ int startPosition = cstNode.getStartPosition();
+ if (startPosition < 0) {
+ startPosition = 0;
+ }
+ if (startPosition > offset) {
+ startPosition = offset;
+ }
+ String textOCL = text.substring(startPosition, offset);
+ Collection<Choice> choices = content.getSyntaxHelp(textOCL, offset);
+ Set<String> duplicated = new HashSet<String>();
+ for (Choice next : choices) {
+ String replacementString = next.getName();
+ if (replacementString.toLowerCase().startsWith(start.toLowerCase())) {
+ switch (next.getKind()) {
+ case OPERATION:
+ if (next.getElement() instanceof EOperation) {
+ Image image = AcceleoUIActivator.getDefault().getImage(
+ "icons/template-editor/completion/Template.gif"); //$NON-NLS-1$
+ EOperation eOperation = (EOperation)next.getElement();
+ String description;
+ if (eOperation.getEContainingClass() != null) {
+ description = eOperation.getEContainingClass().getName() + "." //$NON-NLS-1$
+ + next.getDescription();
+ } else {
+ description = next.getDescription();
+ }
+ if (!duplicated.contains(next.getDescription())) {
+ duplicated.add(next.getDescription());
+ proposals.add(new CompletionProposal(replacementString, offset
+ - start.length(), start.length(), replacementString.length(), image,
+ next.getDescription(), null, description));
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * Computes a list of OCL completion proposals based on the specified location within the text.
+ *
+ * @param proposals
+ * are the completion proposals (in out parameter)
+ */
+ private void computeOCLProposals(List<ICompletionProposal> proposals) {
+ int i = offset;
+ while (i > 0 && Character.isLetterOrDigit(text.charAt(i - 1))) {
+ i--;
+ }
+ String start = text.substring(i, offset);
+ int startPosition = cstNode.getStartPosition();
+ if (startPosition < 0) {
+ startPosition = 0;
+ }
+ if (startPosition > offset) {
+ startPosition = offset;
+ }
+ String textOCL = text.substring(startPosition, offset);
+ Collection<Choice> choices = content.getSyntaxHelp(textOCL, offset);
+ Set<String> duplicated = new HashSet<String>();
+ for (Choice next : choices) {
+ String replacementString = next.getName();
+ if (replacementString.toLowerCase().startsWith(start.toLowerCase())) {
+ switch (next.getKind()) {
+ case OPERATION:
+ addOCLOperationChoice(proposals, next, start, duplicated);
+ break;
+ case SIGNAL:
+ case PROPERTY:
+ String displayProperty = next.getDescription();
+ if (next.getElement() instanceof EStructuralFeature) {
+ displayProperty = getPropertyDisplay((EStructuralFeature)next.getElement());
+ }
+ if (!duplicated.contains(displayProperty)) {
+ duplicated.add(displayProperty);
+ proposals
+ .add(new CompletionProposal(
+ replacementString,
+ offset - start.length(),
+ start.length(),
+ replacementString.length(),
+ AcceleoUIActivator.getDefault().getImage(
+ "icons/template-editor/completion/Property.gif"), displayProperty, //$NON-NLS-1$
+ null, displayProperty));
+ }
+ break;
+ case ENUMERATION_LITERAL:
+ if (!duplicated.contains(replacementString)) {
+ duplicated.add(replacementString);
+ proposals.add(new CompletionProposal(replacementString, offset - start.length(),
+ start.length(), replacementString.length(), AcceleoUIActivator.getDefault()
+ .getImage("icons/template-editor/completion/EnumLiteral.gif"), //$NON-NLS-1$
+ replacementString, null, next.getDescription()));
+ }
+ break;
+ case VARIABLE:
+ String displayVariable;
+ String description;
+ if (IAcceleoConstants.SELF.equals(replacementString) || next.getDescription() == null) {
+ displayVariable = replacementString;
+ description = ""; //$NON-NLS-1$
+ } else {
+ displayVariable = replacementString + ":" + next.getDescription(); //$NON-NLS-1$
+ description = next.getDescription();
+ }
+ if (!duplicated.contains(displayVariable)) {
+ duplicated.add(displayVariable);
+ proposals
+ .add(new CompletionProposal(
+ replacementString,
+ offset - start.length(),
+ start.length(),
+ replacementString.length(),
+ AcceleoUIActivator.getDefault().getImage(
+ "icons/template-editor/completion/Variable.gif"), displayVariable, //$NON-NLS-1$
+ null, description));
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * Adds (or not) an OCL operation in the proposals list.
+ *
+ * @param proposals
+ * is the output proposals list
+ * @param nextOperationChoice
+ * is the next operation to add (or not) in the proposals list
+ * @param start
+ * is the current text used to keep the completion proposals, the name of a valid proposal must
+ * start with this string
+ * @param duplicated
+ * are the descriptions that already appear in the completion list
+ */
+ private void addOCLOperationChoice(List<ICompletionProposal> proposals, Choice nextOperationChoice,
+ String start, Set<String> duplicated) {
+ Image image;
+ if (nextOperationChoice instanceof AcceleoCompletionChoice) {
+ if (((AcceleoCompletionChoice)nextOperationChoice).getAcceleoElement() instanceof org.eclipse.acceleo.model.mtl.Template) {
+ image = AcceleoUIActivator.getDefault().getImage("icons/template-editor/completion/Template.gif"); //$NON-NLS-1$
+ } else if (((AcceleoCompletionChoice)nextOperationChoice).getAcceleoElement() instanceof org.eclipse.acceleo.model.mtl.Query) {
+ image = AcceleoUIActivator.getDefault().getImage("icons/template-editor/completion/Query.gif"); //$NON-NLS-1$
+ } else if (((AcceleoCompletionChoice)nextOperationChoice).getAcceleoElement() instanceof org.eclipse.acceleo.model.mtl.Macro) {
+ image = AcceleoUIActivator.getDefault().getImage("icons/template-editor/completion/Macro.gif"); //$NON-NLS-1$
+ } else {
+ image = AcceleoUIActivator.getDefault()
+ .getImage("icons/template-editor/completion/Operation.gif"); //$NON-NLS-1$
+ }
+ } else {
+ image = AcceleoUIActivator.getDefault().getImage("icons/template-editor/completion/Operation.gif"); //$NON-NLS-1$
+ }
+ if (nextOperationChoice.getElement() instanceof EOperation) {
+ EOperation eOperation = (EOperation)nextOperationChoice.getElement();
+ String replacementStringWithArgsBefore = eOperation.getName() + IAcceleoConstants.PARENTHESIS_BEGIN;
+ String replacementStringWithArgsAfter = ""; //$NON-NLS-1$
+ Iterator<EParameter> eParametersIt = eOperation.getEParameters().iterator();
+ while (eParametersIt.hasNext()) {
+ EParameter eParameter = eParametersIt.next();
+ replacementStringWithArgsAfter += eParameter.getName();
+ if (eParametersIt.hasNext()) {
+ replacementStringWithArgsAfter += ", "; //$NON-NLS-1$
+ }
+ }
+ replacementStringWithArgsAfter += ')';
+ String description;
+ if (eOperation.getEContainingClass() != null) {
+ description = eOperation.getEContainingClass().getName() + "." //$NON-NLS-1$
+ + nextOperationChoice.getDescription();
+ } else {
+ description = nextOperationChoice.getDescription();
+ }
+ if (!duplicated.contains(nextOperationChoice.getDescription())) {
+ duplicated.add(nextOperationChoice.getDescription());
+ proposals.add(new CompletionProposal(replacementStringWithArgsBefore
+ + replacementStringWithArgsAfter, offset - start.length(), start.length(),
+ replacementStringWithArgsBefore.length(), image,
+ nextOperationChoice.getDescription(), null, description));
+ }
+ } else {
+ if (!duplicated.contains(nextOperationChoice.getDescription())) {
+ duplicated.add(nextOperationChoice.getDescription());
+ proposals.add(new CompletionProposal(nextOperationChoice.getName(), offset - start.length(),
+ start.length(), nextOperationChoice.getName().length(), image, nextOperationChoice
+ .getDescription(), null, nextOperationChoice.getDescription()));
+ }
+ }
+ }
+
+ /**
+ * Gets the buffer to display for each structural feature.
+ *
+ * @param eStructuralFeature
+ * is the feature to display
+ * @return the string to display
+ */
+ private String getPropertyDisplay(EStructuralFeature eStructuralFeature) {
+ StringBuffer displayProperty = new StringBuffer();
+ displayProperty.append(eStructuralFeature.getName());
+ if (eStructuralFeature.getEType() != null) {
+ displayProperty.append(':');
+ displayProperty.append(eStructuralFeature.getEType().getName());
+ }
+ if (eStructuralFeature.getLowerBound() == eStructuralFeature.getUpperBound()) {
+ displayProperty.append(' ');
+ displayProperty.append('[');
+ displayProperty.append(eStructuralFeature.getLowerBound());
+ displayProperty.append(']');
+ } else {
+ displayProperty.append(' ');
+ displayProperty.append('[');
+ displayProperty.append(eStructuralFeature.getLowerBound());
+ displayProperty.append(".."); //$NON-NLS-1$
+ if (eStructuralFeature.getUpperBound() == -1) {
+ displayProperty.append("*"); //$NON-NLS-1$
+ } else {
+ displayProperty.append(eStructuralFeature.getUpperBound());
+ }
+ displayProperty.append(']');
+ }
+ return displayProperty.toString();
+ }
+
+ /**
+ * Computes an import declaration based on the specified location within the text.
+ *
+ * @param proposals
+ * are the completion proposals (in out parameter)
+ */
+ private void computeImportProposals(List<ICompletionProposal> proposals) {
+ int i = offset;
+ while (i > 0 && !Character.isWhitespace(text.charAt(i - 1))) {
+ i--;
+ }
+ String start = text.substring(i, offset);
+ Iterator<URI> dependencies = content.getAccessibleOutputFiles().iterator();
+ while (dependencies.hasNext()) {
+ URI uri = dependencies.next();
+ String replacementString = new Path(uri.lastSegment()).removeFileExtension().lastSegment();
+ if (replacementString.toLowerCase().startsWith(start.toLowerCase())) {
+ proposals.add(new CompletionProposal(replacementString, offset - start.length(), start
+ .length(), replacementString.length(), AcceleoUIActivator.getDefault().getImage(
+ "icons/template-editor/completion/Module.gif"), replacementString, null, uri.path())); //$NON-NLS-1$
+ }
+ }
+ }
+
+ /**
+ * Computes a list of meta-model URIs based on the specified location within the text.
+ *
+ * @param proposals
+ * are the completion proposals (in out parameter)
+ */
+ private void computeEPackageProposals(List<ICompletionProposal> proposals) {
+ final String uriImagePath = "icons/template-editor/completion/URI.gif"; //$NON-NLS-1$
+ int i = offset;
+ while (i > 0 && text.charAt(i - 1) != '(' && text.charAt(i - 1) != ',' && text.charAt(i - 1) != '\'') {
+ i--;
+ }
+ String start = text.substring(i, offset);
+ Iterator<String> entries = new TreeSet<String>(EPackage.Registry.INSTANCE.keySet()).iterator();
+ while (entries.hasNext()) {
+ String pURI = entries.next();
+ if (pURI.toLowerCase().startsWith(start.toLowerCase())) {
+ proposals.add(new CompletionProposal(pURI, offset - start.length(), start.length(), pURI
+ .length(), AcceleoUIActivator.getDefault().getImage(uriImagePath), pURI, null, pURI));
+ }
+ }
+ if (start.length() > 0) {
+ entries = new TreeSet<String>(EPackage.Registry.INSTANCE.keySet()).iterator();
+ while (entries.hasNext()) {
+ String pURI = entries.next();
+ EPackage ePackage = EPackage.Registry.INSTANCE.getEPackage(pURI);
+ if (ePackage != null) {
+ String shortName = ePackage.getName();
+ if (shortName.startsWith(start.toLowerCase())) {
+ proposals.add(new CompletionProposal(pURI, offset - start.length(), start.length(),
+ pURI.length(), AcceleoUIActivator.getDefault().getImage(uriImagePath), pURI,
+ null, pURI));
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Computes a list of classifiers based on the specified location within the text.
+ *
+ * @param proposals
+ * are the completion proposals (in out parameter)
+ */
+ private void computeEClassifierProposals(List<ICompletionProposal> proposals) {
+ if (content.getCST() != null) {
+ int i = offset;
+ while (i > 0 && Character.isLetterOrDigit(text.charAt(i - 1))) {
+ i--;
+ }
+ int j = i;
+ while (j > 0 && Character.isWhitespace(text.charAt(j - 1))) {
+ j--;
+ }
+ if (j > 0 && text.charAt(j - 1) == ':') {
+ String start = text.substring(i, offset);
+ Iterator<EClassifier> eClassifierIt = content.getTypes().iterator();
+ while (eClassifierIt.hasNext()) {
+ EClassifier eClassifier = eClassifierIt.next();
+ if (eClassifier.getName().toLowerCase().startsWith(start.toLowerCase())) {
+ proposals.add(new CompletionProposal(eClassifier.getName(), offset - start.length(),
+ start.length(), eClassifier.getName().length(), AcceleoUIActivator.getDefault()
+ .getImage("icons/template-editor/completion/Type.gif"), eClassifier //$NON-NLS-1$
+ .getName(), null, eClassifier.getName()));
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Computes a module declaration pattern based on the specified location within the text.
+ *
+ * @param proposals
+ * are the completion proposals (in out parameter)
+ */
+ private void computeModulePatternProposals(List<ICompletionProposal> proposals) {
+ int i = offset;
+ while (i > 0 && Character.isLetterOrDigit(text.charAt(i - 1))) {
+ i--;
+ }
+ if (i > 0 && text.charAt(i - 1) == '[') {
+ i--;
+ }
+ String start = text.substring(i, offset);
+ StringBuffer tabBuffer = new StringBuffer();
+ while (i > 0 && Character.isWhitespace(text.charAt(i - 1)) && text.charAt(i - 1) != '\n') {
+ tabBuffer.insert(0, text.charAt(i - 1));
+ i--;
+ }
+ if (i == 0 || text.charAt(i - 1) == '\n') {
+ String fileName;
+ if (content.getFile() != null) {
+ fileName = content.getFile().getName();
+ } else {
+ fileName = ""; //$NON-NLS-1$
+ }
+ if (IAcceleoConstants.MODULE.startsWith(start.toLowerCase())
+ || ('[' + IAcceleoConstants.MODULE).startsWith(start.toLowerCase())) {
+ String replacementStringBefore = '[' + IAcceleoConstants.MODULE + ' '
+ + new Path(fileName).removeFileExtension().lastSegment() + "('"; //$NON-NLS-1$
+ String replacementStringAfter = "') /]\n" + tabBuffer.toString(); //$NON-NLS-1$
+ String replacementString = replacementStringBefore + replacementStringAfter;
+ proposals.add(new CompletionProposal(replacementString, offset - start.length(), start
+ .length(), replacementStringBefore.length(), AcceleoUIActivator.getDefault().getImage(
+ "icons/template-editor/completion/Pattern.gif"), //$NON-NLS-1$
+ '[' + IAcceleoConstants.MODULE + ']', null, replacementString));
+ }
+ }
+ }
+
+ /**
+ * Computes a list of patterns based on the specified location within the text.
+ *
+ * @param proposals
+ * are the completion proposals (in out parameter)
+ */
+ private void computePatternsProposals(List<ICompletionProposal> proposals) {
+ int i = offset;
+ while (i > 0 && (Character.isLetterOrDigit(text.charAt(i - 1)) || text.charAt(i - 1) == '@')) {
+ i--;
+ }
+ if (i > 0 && (text.charAt(i - 1) == '[' || text.charAt(i - 1) == ']')) {
+ i--;
+ }
+ String start = text.substring(i, offset);
+ StringBuffer tabBuffer = new StringBuffer();
+ while (i > 0 && Character.isWhitespace(text.charAt(i - 1)) && text.charAt(i - 1) != '\n') {
+ tabBuffer.insert(0, text.charAt(i - 1));
+ i--;
+ }
+ String tab = tabBuffer.toString();
+ Image patternImage = AcceleoUIActivator.getDefault().getImage(
+ "icons/template-editor/completion/Pattern.gif"); //$NON-NLS-1$
+ if (i > 0 && text.charAt(i - 1) == '\n') {
+ // We are not interested by the first line
+ if (content.getCSTParent(cstNode, org.eclipse.acceleo.parser.cst.ModuleElement.class) == null
+ && text.substring(0, i).indexOf('[' + IAcceleoConstants.TEMPLATE) == -1
+ && text.substring(0, i).indexOf('[' + IAcceleoConstants.QUERY) == -1
+ && text.substring(0, i).indexOf('[' + IAcceleoConstants.MACRO) == -1) {
+ if (IAcceleoConstants.IMPORT.startsWith(start.toLowerCase())
+ || ('[' + IAcceleoConstants.IMPORT).startsWith(start.toLowerCase())) {
+ String replacementStringBefore = '[' + IAcceleoConstants.IMPORT + ' ';
+ String replacementStringAfter = " /]\n" + tab; //$NON-NLS-1$
+ String replacementString = replacementStringBefore + replacementStringAfter;
+ proposals.add(new CompletionProposal(replacementString, offset - start.length(), start
+ .length(), replacementStringBefore.length(), patternImage,
+ '[' + IAcceleoConstants.IMPORT + ']', null, replacementString));
+ }
+ }
+ if (!(cstNode instanceof ModuleElement)
+ && content.getCSTParent(cstNode, org.eclipse.acceleo.parser.cst.ModuleElement.class) == null) {
+ computeModuleElementsPatternsProposals(proposals, start, tab, patternImage);
+ }
+ if (cstNode instanceof IfBlock
+ || (cstNode instanceof TextExpression && cstNode.eContainer() instanceof IfBlock)) {
+ if (IAcceleoConstants.ELSE_IF.startsWith(start.toLowerCase())
+ || ('[' + IAcceleoConstants.ELSE_IF).startsWith(start.toLowerCase())) {
+ String replacementStringBefore = '[' + IAcceleoConstants.ELSE_IF + ' ' + '(';
+ String replacementStringAfter = ")]" + '\n' + tab + '\t'; //$NON-NLS-1$
+ String replacementString = replacementStringBefore + replacementStringAfter;
+ proposals.add(new CompletionProposal(replacementString, offset - start.length(), start
+ .length(), replacementStringBefore.length(), patternImage,
+ '[' + IAcceleoConstants.ELSE_IF + ']', null, replacementString));
+ }
+ if (IAcceleoConstants.ELSE.startsWith(start.toLowerCase())
+ || ('[' + IAcceleoConstants.ELSE).startsWith(start.toLowerCase())) {
+ String replacementString = '[' + IAcceleoConstants.ELSE + ']' + '\n' + tab + '\t';
+ proposals.add(new CompletionProposal(replacementString, offset - start.length(), start
+ .length(), replacementString.length(), patternImage,
+ '[' + IAcceleoConstants.ELSE + ']', null, replacementString));
+ }
+ }
+ if (cstNode instanceof LetBlock
+ || (cstNode instanceof TextExpression && cstNode.eContainer() instanceof LetBlock)) {
+ if (IAcceleoConstants.ELSE_LET.startsWith(start.toLowerCase())
+ || ('[' + IAcceleoConstants.ELSE_LET).startsWith(start.toLowerCase())) {
+ String replacementStringBefore = '[' + IAcceleoConstants.ELSE_LET + ' ';
+ String replacementStringAfter = " " + ":" + " " + defaultVariableType + "]" + '\n' //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ + tab + '\t';
+ String replacementString = replacementStringBefore + replacementStringAfter;
+ proposals.add(new CompletionProposal(replacementString, offset - start.length(), start
+ .length(), replacementStringBefore.length(), patternImage,
+ '[' + IAcceleoConstants.ELSE_LET + ']', null, replacementString));
+ }
+ if (IAcceleoConstants.ELSE.startsWith(start.toLowerCase())
+ || ('[' + IAcceleoConstants.ELSE).startsWith(start.toLowerCase())) {
+ String replacementString = '[' + IAcceleoConstants.ELSE + ']' + '\n' + tab + '\t';
+ proposals.add(new CompletionProposal(replacementString, offset - start.length(), start
+ .length(), replacementString.length(), patternImage,
+ '[' + IAcceleoConstants.ELSE + ']', null, replacementString));
+ }
+ }
+ if (!(cstNode instanceof ModelExpression)
+ && (IAcceleoConstants.COMMENT.startsWith(start.toLowerCase()) || ('[' + IAcceleoConstants.COMMENT)
+ .startsWith(start.toLowerCase()))) {
+ String replacementStringBefore = '[' + IAcceleoConstants.COMMENT + ' ';
+ String replacementStringAfter = " /]\n" + tab; //$NON-NLS-1$
+ String replacementString = replacementStringBefore + replacementStringAfter;
+ proposals.add(new CompletionProposal(replacementString, offset - start.length(), start
+ .length(), replacementStringBefore.length(), patternImage,
+ '[' + IAcceleoConstants.COMMENT + ']', null, replacementString));
+ }
+ }
+ if (!start.startsWith("@")) { //$NON-NLS-1$
+ computeBlocksPatternsProposals(proposals, start, tab, patternImage);
+ }
+ computeMainTagPatternsProposals(proposals, start, tab, patternImage);
+ }
+
+ /**
+ * Computes a list of patterns for the main tag (@main).
+ *
+ * @param proposals
+ * are the completion proposals (in out parameter)
+ * @param start
+ * is the beginning text
+ * @param tab
+ * is the current indentation of the text
+ * @param patternImage
+ * is the image to show in the completion popup menu
+ */
+ private void computeMainTagPatternsProposals(List<ICompletionProposal> proposals, String start,
+ String tab, Image patternImage) {
+ if (cstNode instanceof Template || content.getCSTParent(cstNode, Template.class) != null) {
+ if (!(cstNode instanceof ModelExpression)
+ && (IAcceleoConstants.TAG_MAIN.startsWith(start.toLowerCase()) || ('[' + IAcceleoConstants.TAG_MAIN)
+ .startsWith(start.toLowerCase()))) {
+ String replacementStringBefore = '[' + IAcceleoConstants.COMMENT + ' ' + IAcceleoConstants.TAG_MAIN
+ + ' ' + "/]\n" + tab; //$NON-NLS-1$
+ String replacementString = replacementStringBefore;
+ proposals.add(new CompletionProposal(replacementString, offset - start.length(), start
+ .length(), replacementStringBefore.length(), patternImage, IAcceleoConstants.TAG_MAIN,
+ null, replacementString));
+ }
+ }
+ }
+
+ /**
+ * Computes a list of patterns for all the module elements : template, query, macro...
+ *
+ * @param proposals
+ * are the completion proposals (in out parameter)
+ * @param start
+ * is the beginning text
+ * @param tab
+ * is the current indentation of the text
+ * @param patternImage
+ * is the image to show in the completion popup menu
+ */
+ private void computeModuleElementsPatternsProposals(List<ICompletionProposal> proposals, String start,
+ String tab, Image patternImage) {
+ if (IAcceleoConstants.TEMPLATE.startsWith(start.toLowerCase())
+ || ('[' + IAcceleoConstants.TEMPLATE).startsWith(start.toLowerCase())) {
+ String replacementStringBefore = '[' + IAcceleoConstants.TEMPLATE + ' ';
+ String replacementStringAfter = '(' + "e : " + defaultVariableType + ")]\n" + tab //$NON-NLS-1$ //$NON-NLS-2$
+ + '\t' + '\n' + tab + '[' + '/' + IAcceleoConstants.TEMPLATE + ']';
+ String replacementString = replacementStringBefore + replacementStringAfter;
+ proposals.add(new CompletionProposal(replacementString, offset - start.length(), start.length(),
+ replacementStringBefore.length(), patternImage, '[' + IAcceleoConstants.TEMPLATE + ']', null,
+ tab + replacementString));
+ }
+ if (IAcceleoConstants.QUERY.startsWith(start.toLowerCase())
+ || ('[' + IAcceleoConstants.QUERY).startsWith(start.toLowerCase())) {
+ String replacementStringBefore = '[' + IAcceleoConstants.QUERY + ' ';
+ String replacementStringAfter = "(e : " + defaultVariableType + ") : " + defaultVariableType //$NON-NLS-1$ //$NON-NLS-2$
+ + " = /]\n"; //$NON-NLS-1$
+ String replacementString = replacementStringBefore + replacementStringAfter;
+ proposals.add(new CompletionProposal(replacementString, offset - start.length(), start.length(),
+ replacementStringBefore.length(), patternImage, '[' + IAcceleoConstants.QUERY + ']', null,
+ tab + replacementString));
+ }
+ if (IAcceleoConstants.MACRO.startsWith(start.toLowerCase())
+ || ('[' + IAcceleoConstants.MACRO).startsWith(start.toLowerCase())) {
+ String replacementStringBefore = '[' + IAcceleoConstants.MACRO + ' ';
+ String replacementStringAfter = "(e : " + defaultVariableType + ") : " + defaultVariableType //$NON-NLS-1$ //$NON-NLS-2$
+ + "]\n" + tab + '\t' + '\n' + tab + '[' + '/' + IAcceleoConstants.MACRO //$NON-NLS-1$
+ + ']';
+ String replacementString = replacementStringBefore + replacementStringAfter;
+ proposals.add(new CompletionProposal(replacementString, offset - start.length(), start.length(),
+ replacementStringBefore.length(), patternImage, '[' + IAcceleoConstants.MACRO + ']', null,
+ tab + replacementString));
+ }
+ }
+
+ /**
+ * Checks the position and computes a list of patterns for all the blocks : for, if, file...
+ *
+ * @param proposals
+ * are the completion proposals (in out parameter)
+ * @param start
+ * is the beginning text
+ * @param tab
+ * is the current indentation of the text
+ * @param patternImage
+ * is the image to show in the completion popup menu
+ */
+ private void computeBlocksPatternsProposals(List<ICompletionProposal> proposals, String start,
+ String tab, Image patternImage) {
+ if (cstNode instanceof Template) {
+ if (((Template)cstNode).getBody().size() == 0
+ || offset >= ((Template)cstNode).getBody().get(0).getStartPosition()) {
+ computeBlocksPatternsProposalsSub(proposals, start, tab, patternImage);
+ }
+ } else if (cstNode instanceof Block) {
+ computeBlocksPatternsProposalsSub(proposals, start, tab, patternImage);
+ }
+ if (content.getCSTParent(cstNode, org.eclipse.acceleo.parser.cst.ModuleElement.class) != null) {
+ if (cstNode instanceof org.eclipse.acceleo.parser.cst.TextExpression) {
+ int size = proposals.size();
+ computeBlocksPatternsProposalsSub(proposals, start, tab, patternImage);
+ if (proposals.size() == size) {
+ computeBlocksPatternsProposalsSub(proposals, "", tab, patternImage); //$NON-NLS-1$
+ }
+ } else if (cstNode instanceof org.eclipse.acceleo.parser.cst.ModelExpression) {
+ if (start.startsWith("[") && (offset == text.length() || text.charAt(offset) != '/')) { //$NON-NLS-1$
+ computeBlocksPatternsProposalsSub(proposals, start, tab, patternImage);
+ }
+ }
+ }
+ }
+
+ /**
+ * Computes a list of patterns for all the blocks : for, if, file...
+ *
+ * @param proposals
+ * are the completion proposals (in out parameter)
+ * @param start
+ * is the beginning text
+ * @param tab
+ * is the current indentation of the text
+ * @param patternImage
+ * is the image to show in the completion popup menu
+ */
+ private void computeBlocksPatternsProposalsSub(List<ICompletionProposal> proposals, String start,
+ String tab, Image patternImage) {
+ if (IAcceleoConstants.DEFAULT_BEGIN.startsWith(start.toLowerCase())) {
+ String replacementStringBefore = "["; //$NON-NLS-1$
+ String replacementStringAfter = "/]"; //$NON-NLS-1$
+ String replacementString = replacementStringBefore + replacementStringAfter;
+ proposals.add(new CompletionProposal(replacementString, offset - start.length(), start.length(),
+ replacementStringBefore.length(), patternImage, "[ ]", null, replacementString)); //$NON-NLS-1$
+ }
+ if (IAcceleoConstants.FOR.startsWith(start.toLowerCase())
+ || ('[' + IAcceleoConstants.FOR).startsWith(start.toLowerCase())) {
+ String replacementStringBefore = '[' + IAcceleoConstants.FOR + ' ' + '(';
+ String replacementStringAfter = " : " + defaultVariableType + " | )]\n" + tab + '\t' //$NON-NLS-1$ //$NON-NLS-2$
+ + '\n' + tab + '[' + '/' + IAcceleoConstants.FOR + ']';
+ String replacementString = replacementStringBefore + replacementStringAfter;
+ proposals.add(new CompletionProposal(replacementString, offset - start.length(), start.length(),
+ replacementStringBefore.length(), patternImage, '[' + IAcceleoConstants.FOR + ']', null, tab
+ + replacementString));
+ }
+ if (IAcceleoConstants.IF.startsWith(start.toLowerCase())
+ || ('[' + IAcceleoConstants.IF).startsWith(start.toLowerCase())) {
+ String replacementStringBefore = '[' + IAcceleoConstants.IF + ' ' + '(';
+ String replacementStringAfter = ")]\n" + tab + '\t' + '\n' + tab + '[' //$NON-NLS-1$
+ + '/' + IAcceleoConstants.IF + ']';
+ String replacementString = replacementStringBefore + replacementStringAfter;
+ proposals.add(new CompletionProposal(replacementString, offset - start.length(), start.length(),
+ replacementStringBefore.length(), patternImage, '[' + IAcceleoConstants.IF + ']', null, tab
+ .toString()
+ + replacementString));
+ }
+ if (IAcceleoConstants.FILE.startsWith(start.toLowerCase())
+ || ('[' + IAcceleoConstants.FILE).startsWith(start.toLowerCase())) {
+ computeFileBlockPatternsProposals(proposals, start, tab, patternImage, true);
+ computeFileBlockPatternsProposals(proposals, start, tab, patternImage, false);
+ }
+ if (IAcceleoConstants.LET.startsWith(start.toLowerCase())
+ || ('[' + IAcceleoConstants.LET).startsWith(start.toLowerCase())) {
+ String replacementStringBefore = '[' + IAcceleoConstants.LET + ' ';
+ String replacementStringAfter = " : " + defaultVariableType + "]\n" + tab + '\t' //$NON-NLS-1$ //$NON-NLS-2$
+ + '\n' + tab + '[' + '/' + IAcceleoConstants.LET + ']';
+ String replacementString = replacementStringBefore + replacementStringAfter;
+ proposals.add(new CompletionProposal(replacementString, offset - start.length(), start.length(),
+ replacementStringBefore.length(), patternImage, '[' + IAcceleoConstants.LET + ']', null, tab
+ .toString()
+ + replacementString));
+ }
+ if (IAcceleoConstants.TRACE.startsWith(start.toLowerCase())
+ || ('[' + IAcceleoConstants.TRACE).startsWith(start.toLowerCase())) {
+ String replacementStringBefore = '[' + IAcceleoConstants.TRACE + " ('"; //$NON-NLS-1$
+ String replacementStringAfter = "')]\n" + tab + '\t' + '\n' + tab + '[' //$NON-NLS-1$
+ + '/' + IAcceleoConstants.TRACE + ']';
+ String replacementString = replacementStringBefore + replacementStringAfter;
+ proposals.add(new CompletionProposal(replacementString, offset - start.length(), start.length(),
+ replacementStringBefore.length(), patternImage, '[' + IAcceleoConstants.TRACE + ']', null,
+ tab + replacementString));
+ }
+ if (IAcceleoConstants.PROTECTED_AREA.startsWith(start.toLowerCase())
+ || ('[' + IAcceleoConstants.PROTECTED_AREA).startsWith(start.toLowerCase())) {
+ String replacementStringBefore = '[' + IAcceleoConstants.PROTECTED_AREA + " ('"; //$NON-NLS-1$
+ String replacementStringAfter = "')]\n" + tab + '\t' + '\n' + tab + '[' //$NON-NLS-1$
+ + '/' + IAcceleoConstants.PROTECTED_AREA + ']';
+ String replacementString = replacementStringBefore + replacementStringAfter;
+ proposals.add(new CompletionProposal(replacementString, offset - start.length(), start.length(),
+ replacementStringBefore.length(), patternImage, '[' + IAcceleoConstants.PROTECTED_AREA + ']',
+ null, tab + replacementString));
+ }
+ if (IAcceleoConstants.SUPER.startsWith(start.toLowerCase())
+ || ('[' + IAcceleoConstants.SUPER).startsWith(start.toLowerCase())) {
+ String replacementStringBefore = '[' + IAcceleoConstants.SUPER;
+ String replacementStringAfter = "/]"; //$NON-NLS-1$
+ String replacementString = replacementStringBefore + replacementStringAfter;
+ proposals.add(new CompletionProposal(replacementString, offset - start.length(), start.length(),
+ replacementStringBefore.length(), patternImage, '[' + IAcceleoConstants.SUPER + ']', null,
+ replacementString));
+ }
+ if (IAcceleoConstants.DEFAULT_BEGIN.startsWith(start.toLowerCase())) {
+ String replacementString = "[ '[' /] "; //$NON-NLS-1$
+ proposals.add(new CompletionProposal(replacementString, offset - start.length(), start.length(),
+ replacementString.length(), patternImage, "'['", null, replacementString)); //$NON-NLS-1$
+ }
+ if ("".equals(start.toLowerCase())) { //$NON-NLS-1$
+ String replacementString = "[ ']' /] "; //$NON-NLS-1$
+ proposals.add(new CompletionProposal(replacementString, offset - start.length(), start.length(),
+ replacementString.length(), patternImage, "']'", null, replacementString)); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Computes a list of patterns for the file block.
+ *
+ * @param proposals
+ * are the completion proposals (in out parameter)
+ * @param start
+ * is the beginning text
+ * @param tab
+ * is the current indentation of the text
+ * @param patternImage
+ * is the image to show in the completion popup menu
+ * @param withMainTag
+ * indicates if a main tag (@main) must be added before the file block
+ */
+ private void computeFileBlockPatternsProposals(List<ICompletionProposal> proposals, String start,
+ String tab, Image patternImage, boolean withMainTag) {
+ String mainTagText;
+ if (withMainTag) {
+ mainTagText = '[' + IAcceleoConstants.COMMENT + ' ' + IAcceleoConstants.TAG_MAIN + ' ' + '/' + ']' + '\n'
+ + tab;
+ } else {
+ mainTagText = ""; //$NON-NLS-1$
+ }
+ String replacementStringBefore = mainTagText + '[' + IAcceleoConstants.FILE + ' ' + "('file://"; //$NON-NLS-1$
+ org.eclipse.acceleo.parser.cst.ModuleElement cstModuleElement = (org.eclipse.acceleo.parser.cst.ModuleElement)content
+ .getCSTParent(cstNode, org.eclipse.acceleo.parser.cst.ModuleElement.class);
+ String currentModuleElementName;
+ if (cstModuleElement != null) {
+ currentModuleElementName = cstModuleElement.getName();
+ } else {
+ currentModuleElementName = ""; //$NON-NLS-1$
+ }
+ String replacementStringAfter = "', false, '" + currentModuleElementName.toUpperCase() //$NON-NLS-1$
+ + "-ID')]\n" + tab + '\t' + '\n' + tab + '[' + '/' //$NON-NLS-1$
+ + IAcceleoConstants.FILE + ']';
+ String replacementString = replacementStringBefore + replacementStringAfter;
+ String displayString = '[' + IAcceleoConstants.FILE + ']';
+ if (withMainTag) {
+ displayString += " - " + IAcceleoConstants.TAG_MAIN; //$NON-NLS-1$
+ }
+ proposals.add(new CompletionProposal(replacementString, offset - start.length(), start.length(),
+ replacementStringBefore.length(), patternImage, displayString, null, tab.toString()
+ + replacementString));
+ }
+
+ /**
+ * Computes a list of keywords based on the specified location within the text.
+ *
+ * @param proposals
+ * are the completion proposals (in out parameter)
+ */
+ private void computeKeywordsProposals(List<ICompletionProposal> proposals) {
+ if (cstNode != null) {
+ int i = offset;
+ while (i > 0 && Character.isLetterOrDigit(text.charAt(i - 1))) {
+ i--;
+ }
+ String start = text.substring(i, offset);
+ int bHeader = cstNode.getStartPosition();
+ String bHeaderText;
+ if (bHeader > -1 && bHeader < i) {
+ bHeaderText = text.substring(bHeader, i).trim();
+ } else {
+ bHeaderText = ""; //$NON-NLS-1$
+ }
+ Image keywordImage = AcceleoUIActivator.getDefault().getImage(
+ "icons/template-editor/completion/Keyword.gif"); //$NON-NLS-1$
+ if (cstNode instanceof org.eclipse.acceleo.parser.cst.Module) {
+ if (isHeaderAfterParenthesis(bHeaderText)
+ && ((org.eclipse.acceleo.parser.cst.Module)cstNode).getExtends().size() == 0) {
+ computeKeywordProposal(proposals, start, IAcceleoConstants.EXTENDS + ' ', "", keywordImage); //$NON-NLS-1$
+ }
+ }
+ if (cstNode instanceof org.eclipse.acceleo.parser.cst.ModelExpression
+ && cstNode.eContainingFeature() == CstPackage.eINSTANCE.getBlock_Body()) {
+ computeKeywordsProposalsInTemplateInvocationHeader(proposals, start, bHeaderText,
+ keywordImage);
+ }
+ if (cstNode instanceof org.eclipse.acceleo.parser.cst.Template) {
+ computeKeywordsProposalsInTemplateHeader(proposals, start, bHeaderText, keywordImage);
+ }
+ if (cstNode instanceof org.eclipse.acceleo.parser.cst.Macro) {
+ computeKeywordsProposalsInMacroHeader(proposals, start, bHeaderText, keywordImage);
+ }
+ if (cstNode instanceof org.eclipse.acceleo.parser.cst.ForBlock) {
+ computeKeywordsProposalsInForBlockHeader(proposals, start, bHeaderText, keywordImage);
+ }
+ }
+ }
+
+ /**
+ * Computes a list of keywords for a 'Template' header.
+ *
+ * @param proposals
+ * are the completion proposals (in out parameter)
+ * @param start
+ * is the beginning text of the candidates
+ * @param bHeaderText
+ * is the current beginning text of the header, from the beginning index to the current offset
+ * @param keywordImage
+ * is the image to show in the completion popup menu
+ */
+ private void computeKeywordsProposalsInTemplateHeader(List<ICompletionProposal> proposals, String start,
+ String bHeaderText, Image keywordImage) {
+ if (bHeaderText.equals(IAcceleoConstants.TEMPLATE)) {
+ computeKeywordProposal(proposals, start, IAcceleoConstants.VISIBILITY_KIND_PUBLIC + ' ', "", //$NON-NLS-1$
+ keywordImage);
+ computeKeywordProposal(proposals, start, IAcceleoConstants.VISIBILITY_KIND_PROTECTED + ' ', "", //$NON-NLS-1$
+ keywordImage);
+ computeKeywordProposal(proposals, start, IAcceleoConstants.VISIBILITY_KIND_PRIVATE + ' ', "", //$NON-NLS-1$
+ keywordImage);
+ }
+ if (isHeaderAfterParenthesis(bHeaderText)) {
+ StringBuffer bHeaderBuffer = new StringBuffer(bHeaderText);
+ Sequence pGuard = new Sequence(IAcceleoConstants.GUARD, IAcceleoConstants.PARENTHESIS_BEGIN);
+ Sequence pInit = new Sequence(IAcceleoConstants.BRACKETS_BEGIN);
+ if (((org.eclipse.acceleo.parser.cst.Template)cstNode).getOverrides().size() == 0
+ && pGuard.search(bHeaderBuffer).b() == -1 && pInit.search(bHeaderBuffer).b() == -1) {
+ computeKeywordProposal(proposals, start, IAcceleoConstants.OVERRIDES + ' ', "", keywordImage); //$NON-NLS-1$
+ }
+ if (((org.eclipse.acceleo.parser.cst.Template)cstNode).getGuard() == null
+ && pInit.search(bHeaderBuffer).b() == -1) {
+ computeKeywordProposal(proposals, start, IAcceleoConstants.GUARD + ' '
+ + IAcceleoConstants.PARENTHESIS_BEGIN, IAcceleoConstants.PARENTHESIS_END, keywordImage);
+ }
+ if (((org.eclipse.acceleo.parser.cst.Template)cstNode).getInit() == null
+ && "{".startsWith(start.toLowerCase())) { //$NON-NLS-1$
+ String replacementStringBefore = "{ "; //$NON-NLS-1$
+ String replacementStringAfter = ": " + defaultVariableType + "; }"; //$NON-NLS-1$ //$NON-NLS-2$
+ String replacementString = replacementStringBefore + replacementStringAfter;
+ proposals.add(new CompletionProposal(replacementString, offset - start.length(), start
+ .length(), replacementStringBefore.length(), keywordImage, "{ }", null, //$NON-NLS-1$
+ replacementString));
+ }
+ }
+ }
+
+ /**
+ * Computes a list of keywords for a 'Macro' header.
+ *
+ * @param proposals
+ * are the completion proposals (in out parameter)
+ * @param start
+ * is the beginning text of the candidates
+ * @param bHeaderText
+ * is the current beginning text of the header, from the beginning index to the current offset
+ * @param keywordImage
+ * is the image to show in the completion popup menu
+ */
+ private void computeKeywordsProposalsInMacroHeader(List<ICompletionProposal> proposals, String start,
+ String bHeaderText, Image keywordImage) {
+ if (bHeaderText.equals(IAcceleoConstants.MACRO)) {
+ computeKeywordProposal(proposals, start, IAcceleoConstants.VISIBILITY_KIND_PUBLIC + ' ', "", //$NON-NLS-1$
+ keywordImage);
+ computeKeywordProposal(proposals, start, IAcceleoConstants.VISIBILITY_KIND_PROTECTED + ' ', "", //$NON-NLS-1$
+ keywordImage);
+ computeKeywordProposal(proposals, start, IAcceleoConstants.VISIBILITY_KIND_PRIVATE + ' ', "", //$NON-NLS-1$
+ keywordImage);
+ }
+ }
+
+ /**
+ * Computes a list of keywords for a 'TemplateInvocation'.
+ *
+ * @param proposals
+ * are the completion proposals (in out parameter)
+ * @param start
+ * is the beginning text of the candidates
+ * @param bHeaderText
+ * is the current beginning text of the header, from the beginning index to the current offset
+ * @param keywordImage
+ * is the image to show in the completion popup menu
+ */
+ private void computeKeywordsProposalsInTemplateInvocationHeader(List<ICompletionProposal> proposals,
+ String start, String bHeaderText, Image keywordImage) {
+ if (isHeaderAfterParenthesis(bHeaderText) || bHeaderText.indexOf(IAcceleoConstants.SUPER) > -1) {
+ StringBuffer bHeaderBuffer = new StringBuffer(bHeaderText);
+ Sequence pSeparator = new Sequence(IAcceleoConstants.SEPARATOR, IAcceleoConstants.PARENTHESIS_BEGIN);
+ Sequence pAfter = new Sequence(IAcceleoConstants.AFTER, IAcceleoConstants.PARENTHESIS_BEGIN);
+ Sequence pGuard = new Sequence(IAcceleoConstants.GUARD, IAcceleoConstants.PARENTHESIS_BEGIN);
+ if (((org.eclipse.acceleo.parser.cst.ModelExpression)cstNode).getBefore() == null) {
+ if (pSeparator.search(bHeaderBuffer).b() == -1 && pAfter.search(bHeaderBuffer).b() == -1
+ && pGuard.search(bHeaderBuffer).b() == -1) {
+ computeKeywordProposal(proposals, start, IAcceleoConstants.BEFORE + ' '
+ + IAcceleoConstants.PARENTHESIS_BEGIN, IAcceleoConstants.PARENTHESIS_END, keywordImage);
+ }
+ }
+ if (((org.eclipse.acceleo.parser.cst.ModelExpression)cstNode).getEach() == null
+ && pAfter.search(bHeaderBuffer).b() == -1 && pGuard.search(bHeaderBuffer).b() == -1) {
+ computeKeywordProposal(proposals, start, IAcceleoConstants.SEPARATOR + ' '
+ + IAcceleoConstants.PARENTHESIS_BEGIN, IAcceleoConstants.PARENTHESIS_END, keywordImage);
+ }
+ if (((org.eclipse.acceleo.parser.cst.ModelExpression)cstNode).getAfter() == null
+ && pGuard.search(bHeaderBuffer).b() == -1) {
+ computeKeywordProposal(proposals, start, IAcceleoConstants.AFTER + ' '
+ + IAcceleoConstants.PARENTHESIS_BEGIN, IAcceleoConstants.PARENTHESIS_END, keywordImage);
+ }
+ }
+ }
+
+ /**
+ * Computes a list of keywords for a 'ForBlock' header.
+ *
+ * @param proposals
+ * are the completion proposals (in out parameter)
+ * @param start
+ * is the beginning text of the candidates
+ * @param bHeaderText
+ * is the current beginning text of the header, from the beginning index to the current offset
+ * @param keywordImage
+ * is the image to show in the completion popup menu
+ */
+ private void computeKeywordsProposalsInForBlockHeader(List<ICompletionProposal> proposals, String start,
+ String bHeaderText, Image keywordImage) {
+ if (isHeaderAfterParenthesis(bHeaderText)) {
+ StringBuffer bHeaderBuffer = new StringBuffer(bHeaderText);
+ Sequence pSeparator = new Sequence(IAcceleoConstants.SEPARATOR, IAcceleoConstants.PARENTHESIS_BEGIN);
+ Sequence pAfter = new Sequence(IAcceleoConstants.AFTER, IAcceleoConstants.PARENTHESIS_BEGIN);
+ Sequence pGuard = new Sequence(IAcceleoConstants.GUARD, IAcceleoConstants.PARENTHESIS_BEGIN);
+ Sequence pInit = new Sequence(IAcceleoConstants.BRACKETS_BEGIN);
+ if (((org.eclipse.acceleo.parser.cst.ForBlock)cstNode).getBefore() == null) {
+ if (pSeparator.search(bHeaderBuffer).b() == -1 && pAfter.search(bHeaderBuffer).b() == -1
+ && pGuard.search(bHeaderBuffer).b() == -1 && pInit.search(bHeaderBuffer).b() == -1) {
+ computeKeywordProposal(proposals, start, IAcceleoConstants.BEFORE + ' '
+ + IAcceleoConstants.PARENTHESIS_BEGIN, IAcceleoConstants.PARENTHESIS_END, keywordImage);
+ }
+ }
+ if (((org.eclipse.acceleo.parser.cst.ForBlock)cstNode).getEach() == null
+ && pAfter.search(bHeaderBuffer).b() == -1 && pGuard.search(bHeaderBuffer).b() == -1
+ && pInit.search(bHeaderBuffer).b() == -1) {
+ computeKeywordProposal(proposals, start, IAcceleoConstants.SEPARATOR + ' '
+ + IAcceleoConstants.PARENTHESIS_BEGIN, IAcceleoConstants.PARENTHESIS_END, keywordImage);
+ }
+ if (((org.eclipse.acceleo.parser.cst.ForBlock)cstNode).getAfter() == null
+ && pGuard.search(bHeaderBuffer).b() == -1 && pInit.search(bHeaderBuffer).b() == -1) {
+ computeKeywordProposal(proposals, start, IAcceleoConstants.AFTER + ' '
+ + IAcceleoConstants.PARENTHESIS_BEGIN, IAcceleoConstants.PARENTHESIS_END, keywordImage);
+ }
+ if (((org.eclipse.acceleo.parser.cst.ForBlock)cstNode).getGuard() == null
+ && pInit.search(bHeaderBuffer).b() == -1) {
+ computeKeywordProposal(proposals, start, IAcceleoConstants.GUARD + ' '
+ + IAcceleoConstants.PARENTHESIS_BEGIN, IAcceleoConstants.PARENTHESIS_END, keywordImage);
+ }
+ if (((org.eclipse.acceleo.parser.cst.ForBlock)cstNode).getInit() == null && "{".startsWith(start)) { //$NON-NLS-1$
+ String replacementStringBefore = "{ "; //$NON-NLS-1$
+ String replacementStringAfter = ": " + defaultVariableType + "; }"; //$NON-NLS-1$ //$NON-NLS-2$
+ String replacementString = replacementStringBefore + replacementStringAfter;
+ proposals.add(new CompletionProposal(replacementString, offset - start.length(), start
+ .length(), replacementStringBefore.length(), keywordImage, "{ }", null, //$NON-NLS-1$
+ replacementString));
+ }
+ }
+ }
+
+ /**
+ * Indicates if there are parenthesis in the text, and if there are finished. It works only if we are
+ * before ']'
+ *
+ * @param aText
+ * is the text to parse
+ * @return true if there are parenthesis in the text, and if there are finished
+ */
+ private boolean isHeaderAfterParenthesis(String aText) {
+ final String tag = "___TAG___"; //$NON-NLS-1$
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(aText);
+ buffer.append(tag);
+ Sequence literalEscape = new Sequence(IAcceleoConstants.LITERAL_ESCAPE);
+ SequenceBlock pLiteral = new SequenceBlock(new Sequence(IAcceleoConstants.LITERAL_BEGIN), new Sequence(
+ IAcceleoConstants.LITERAL_END), literalEscape, false, null);
+ SequenceBlock pParenthesis = new SequenceBlock(new Sequence(IAcceleoConstants.PARENTHESIS_BEGIN),
+ new Sequence(IAcceleoConstants.PARENTHESIS_END), null, true, new SequenceBlock[] {pLiteral});
+ Sequence pHeaderEnd = new Sequence(IAcceleoConstants.DEFAULT_END);
+ Sequence pTag = new Sequence(tag);
+ return (pHeaderEnd.search(buffer, 0, buffer.length(), null, new SequenceBlock[] {pLiteral,}).b() == -1)
+ && (pParenthesis.search(buffer, 0, buffer.length()).b() > -1)
+ && (pTag.search(buffer, 0, buffer.length(), null,
+ new SequenceBlock[] {pLiteral, pParenthesis,}).b() > -1);
+ }
+
+ /**
+ * Creates a keyword proposal.
+ *
+ * @param proposals
+ * are the completion proposals (in out parameter)
+ * @param start
+ * is the beginning text
+ * @param replacementStringBefore
+ * is the replacement string before the new offset
+ * @param replacementStringAfter
+ * is the replacement string after the new offset
+ * @param keywordImage
+ * is the image to show in the completion popup menu
+ */
+ private void computeKeywordProposal(List<ICompletionProposal> proposals, String start,
+ String replacementStringBefore, String replacementStringAfter, Image keywordImage) {
+ String replacementString = replacementStringBefore + replacementStringAfter;
+ if (replacementString.toLowerCase().startsWith(start.toLowerCase())) {
+ proposals.add(new CompletionProposal(replacementString, offset - start.length(), start.length(),
+ replacementStringBefore.length(), keywordImage, replacementString, null,
+ replacementString));
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#computeContextInformation(org.eclipse.jface.text.ITextViewer,
+ * int)
+ */
+ public IContextInformation[] computeContextInformation(ITextViewer viewer, int documentOffset) {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getCompletionProposalAutoActivationCharacters()
+ */
+ public char[] getCompletionProposalAutoActivationCharacters() {
+ // TODO JMU should return a copy of the array to avoid accidental modifications.
+ return AUTO_ACTIVATION_CHARACTERS;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getContextInformationAutoActivationCharacters()
+ */
+ public char[] getContextInformationAutoActivationCharacters() {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getContextInformationValidator()
+ */
+ public IContextInformationValidator getContextInformationValidator() {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getErrorMessage()
+ */
+ public String getErrorMessage() {
+ return null;
+ }
+
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoConfiguration.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoConfiguration.java
new file mode 100644
index 0000000..8930e40
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoConfiguration.java
@@ -0,0 +1,212 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.editors.template;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.acceleo.internal.ide.ui.editors.template.scanner.AbstractAcceleoScanner;
+import org.eclipse.acceleo.internal.ide.ui.editors.template.scanner.AcceleoBehavioralFeatureScanner;
+import org.eclipse.acceleo.internal.ide.ui.editors.template.scanner.AcceleoBlockScanner;
+import org.eclipse.acceleo.internal.ide.ui.editors.template.scanner.AcceleoCommentScanner;
+import org.eclipse.acceleo.internal.ide.ui.editors.template.scanner.AcceleoDefaultScanner;
+import org.eclipse.acceleo.internal.ide.ui.editors.template.scanner.AcceleoForScanner;
+import org.eclipse.acceleo.internal.ide.ui.editors.template.scanner.AcceleoIfScanner;
+import org.eclipse.acceleo.internal.ide.ui.editors.template.scanner.AcceleoLetScanner;
+import org.eclipse.acceleo.internal.ide.ui.editors.template.scanner.AcceleoProtectedAreaScanner;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.DefaultTextDoubleClickStrategy;
+import org.eclipse.jface.text.ITextDoubleClickStrategy;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.contentassist.ContentAssistant;
+import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
+import org.eclipse.jface.text.contentassist.IContentAssistant;
+import org.eclipse.jface.text.presentation.IPresentationReconciler;
+import org.eclipse.jface.text.presentation.PresentationReconciler;
+import org.eclipse.jface.text.reconciler.IReconciler;
+import org.eclipse.jface.text.reconciler.MonoReconciler;
+import org.eclipse.jface.text.rules.DefaultDamagerRepairer;
+import org.eclipse.jface.text.source.IAnnotationHover;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.ui.editors.text.TextSourceViewerConfiguration;
+
+/**
+ * This class bundles the configuration space of a Acceleo template editor.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class AcceleoConfiguration extends TextSourceViewerConfiguration {
+
+ /**
+ * The delay after which the content assistant is automatically invoked if the cursor is behind an auto
+ * activation character.
+ */
+ private static final int COMPLETION_AUTO_ACTIVATION_DELAY = 1000;
+
+ /**
+ * The editor.
+ */
+ protected AcceleoEditor editor;
+
+ /**
+ * The scanners of the source configuration.
+ */
+ private AbstractAcceleoScanner[] scanners;
+
+ /**
+ * Constructor.
+ *
+ * @param editor
+ * is the source editor
+ * @param preferenceStore
+ * The preference store, can be read-only.
+ */
+ public AcceleoConfiguration(AcceleoEditor editor, IPreferenceStore preferenceStore) {
+ this.editor = editor;
+ this.fPreferenceStore = preferenceStore;
+ }
+
+ /**
+ * Gets the scanners of the source configuration.
+ *
+ * @return the scanners
+ */
+ protected AbstractAcceleoScanner[] getScanners() {
+ if (scanners == null) {
+ List<AbstractAcceleoScanner> list = new ArrayList<AbstractAcceleoScanner>();
+ list.add(new AcceleoBehavioralFeatureScanner(editor.getColorManager()));
+ list.add(new AcceleoForScanner(editor.getColorManager()));
+ list.add(new AcceleoIfScanner(editor.getColorManager()));
+ list.add(new AcceleoLetScanner(editor.getColorManager()));
+ list.add(new AcceleoProtectedAreaScanner(editor.getColorManager()));
+ list.add(new AcceleoCommentScanner(editor.getColorManager()));
+ list.add(new AcceleoBlockScanner(editor.getColorManager()));
+ list.add(new AcceleoDefaultScanner(editor.getColorManager()));
+ scanners = list.toArray(new AbstractAcceleoScanner[list.size()]);
+ }
+ return scanners;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.jface.text.source.SourceViewerConfiguration#getConfiguredContentTypes(org.eclipse.jface.text.source.ISourceViewer)
+ */
+ @Override
+ public String[] getConfiguredContentTypes(ISourceViewer sourceViewer) {
+ AbstractAcceleoScanner[] acceleoScanners = getScanners();
+ String[] result = new String[acceleoScanners.length];
+ for (int i = 0; i < acceleoScanners.length; i++) {
+ AbstractAcceleoScanner scanner = acceleoScanners[i];
+ result[i] = scanner.getConfiguredContentType();
+ }
+ return result;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.jface.text.source.SourceViewerConfiguration#getDoubleClickStrategy(org.eclipse.jface.text.source.ISourceViewer,
+ * java.lang.String)
+ */
+ @Override
+ public ITextDoubleClickStrategy getDoubleClickStrategy(ISourceViewer sourceViewer, String contentType) {
+ return new DefaultTextDoubleClickStrategy() {
+ @Override
+ public void doubleClicked(ITextViewer part) {
+ super.doubleClicked(part);
+ Point point = part.getSelectedRange();
+ if (point != null) {
+ int posBegin = point.x;
+ int posEnd = point.y;
+ editor.updateSelection(posBegin, posEnd);
+ }
+ }
+ };
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.jface.text.source.SourceViewerConfiguration#getPresentationReconciler(org.eclipse.jface.text.source.ISourceViewer)
+ */
+ @Override
+ public IPresentationReconciler getPresentationReconciler(ISourceViewer sourceViewer) {
+ PresentationReconciler reconciler = new PresentationReconciler();
+ AbstractAcceleoScanner[] acceleoScanners = getScanners();
+ for (int i = 0; i < acceleoScanners.length; i++) {
+ AbstractAcceleoScanner scanner = acceleoScanners[i];
+ DefaultDamagerRepairer dr = new DefaultDamagerRepairer(scanner);
+ reconciler.setDamager(dr, scanner.getConfiguredContentType());
+ reconciler.setRepairer(dr, scanner.getConfiguredContentType());
+ }
+ return reconciler;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.jface.text.source.SourceViewerConfiguration#getContentAssistant(org.eclipse.jface.text.source.ISourceViewer)
+ */
+ @Override
+ public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) {
+ ContentAssistant assistant = new ContentAssistant();
+ assistant.setDocumentPartitioning(getConfiguredDocumentPartitioning(sourceViewer));
+ IContentAssistProcessor processor = new AcceleoCompletionProcessor(editor.getContent());
+ AbstractAcceleoScanner[] acceleoScanners = getScanners();
+ for (int i = 0; i < acceleoScanners.length; i++) {
+ AbstractAcceleoScanner scanner = acceleoScanners[i];
+ if (!(scanner instanceof AcceleoCommentScanner)) {
+ assistant.setContentAssistProcessor(processor, scanner.getConfiguredContentType());
+ }
+ }
+ assistant.enableAutoActivation(true);
+ assistant.setAutoActivationDelay(COMPLETION_AUTO_ACTIVATION_DELAY);
+ assistant.setProposalPopupOrientation(IContentAssistant.PROPOSAL_OVERLAY);
+ assistant.setInformationControlCreator(getInformationControlCreator(sourceViewer));
+ return assistant;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.jface.text.source.SourceViewerConfiguration#getAnnotationHover(org.eclipse.jface.text.source.ISourceViewer)
+ */
+ @Override
+ public IAnnotationHover getAnnotationHover(ISourceViewer sourceViewer) {
+ return new AcceleoHover(editor);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.jface.text.source.SourceViewerConfiguration#getReconciler(org.eclipse.jface.text.source.ISourceViewer)
+ */
+ @Override
+ public IReconciler getReconciler(ISourceViewer sourceViewer) {
+ return new MonoReconciler(new AcceleoTemplateReconcilingStrategy(editor), false);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.ui.editors.text.TextSourceViewerConfiguration#getHyperlinkDetectorTargets(org.eclipse.jface.text.source.ISourceViewer)
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ protected Map getHyperlinkDetectorTargets(ISourceViewer sourceViewer) {
+ Map targets = super.getHyperlinkDetectorTargets(sourceViewer);
+ targets.put("org.eclipse.acceleo.ide.ui.AcceleoTemplateSource", editor); //$NON-NLS-1$
+ return targets;
+ }
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoDocumentProvider.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoDocumentProvider.java
new file mode 100644
index 0000000..f80f9a4
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoDocumentProvider.java
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.editors.template;
+
+import org.eclipse.acceleo.internal.ide.ui.editors.template.scanner.AcceleoPartitionScanner;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentPartitioner;
+import org.eclipse.jface.text.IPositionUpdater;
+import org.eclipse.jface.text.rules.FastPartitioner;
+import org.eclipse.ui.editors.text.FileDocumentProvider;
+
+/**
+ * Shared document provider for the Acceleo editor.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class AcceleoDocumentProvider extends FileDocumentProvider {
+
+ /**
+ * The editor.
+ */
+ private AcceleoEditor editor;
+
+ /**
+ * A new position updater. A position updater is responsible for adapting document positions. It is called
+ * when a modification has been detected in the document.
+ */
+ private IPositionUpdater positionUpdater;
+
+ /**
+ * Constructor.
+ *
+ * @param editor
+ * is the editor
+ */
+ public AcceleoDocumentProvider(AcceleoEditor editor) {
+ super();
+ this.editor = editor;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.ui.editors.text.StorageDocumentProvider#createDocument(java.lang.Object)
+ */
+ @Override
+ protected IDocument createDocument(Object element) throws CoreException {
+ IDocument document = super.createDocument(element);
+ if (document != null) {
+ IDocumentPartitioner partitioner = new FastPartitioner(new AcceleoPartitionScanner(),
+ AcceleoPartitionScanner.LEGAL_CONTENT_TYPES);
+ partitioner.connect(document);
+ document.setDocumentPartitioner(partitioner);
+ if (positionUpdater == null) {
+ positionUpdater = new IPositionUpdater() {
+ public void update(DocumentEvent event) {
+ handlePositionUpdate(event.getOffset(), event.getOffset() + event.getLength(), event
+ .getText());
+ }
+ };
+ document.addPositionUpdater(positionUpdater);
+ }
+ }
+ return document;
+ }
+
+ /**
+ * A position updater is responsible for adapting document positions. This method is called by a position
+ * updater. A modification has been detected in the template text, at the specified start, until the
+ * character at index end - 1 or to the end of the sequence if no such character exists.
+ *
+ * @param posBegin
+ * the beginning index, inclusive
+ * @param posEnd
+ * the ending index, exclusive
+ * @param newText
+ * the string that will replace previous contents
+ */
+ private void handlePositionUpdate(int posBegin, int posEnd, String newText) {
+ if (editor.getContent() != null) {
+ EObject cstNode = editor.getContent().updateCST(posBegin, posEnd, newText);
+ if (cstNode != null) {
+ AcceleoOutlinePage outline = editor.getContentOutlinePage();
+ if (outline.getControl() != null && !outline.getControl().isDisposed()) {
+ outline.refresh(cstNode);
+ }
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.ui.texteditor.AbstractDocumentProvider#disconnected()
+ */
+ @Override
+ protected void disconnected() {
+ super.disconnected();
+ if (positionUpdater != null && editor.getEditorInput() != null) {
+ // TODO VERIFY
+ IDocument document = getDocument(editor.getEditorInput());
+ if (document != null) {
+ document.removePositionUpdater(positionUpdater);
+ }
+ }
+ }
+
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoEditor.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoEditor.java
new file mode 100644
index 0000000..e7b4c0c
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoEditor.java
@@ -0,0 +1,513 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.editors.template;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.acceleo.ide.ui.AcceleoUIActivator;
+import org.eclipse.acceleo.ide.ui.natures.AcceleoNature;
+import org.eclipse.acceleo.internal.ide.ui.AcceleoUIMessages;
+import org.eclipse.acceleo.parser.cst.CSTNode;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.jdt.ui.PreferenceConstants;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.text.source.IVerticalRuler;
+import org.eclipse.jface.text.source.SourceViewerConfiguration;
+import org.eclipse.jface.text.source.projection.ProjectionAnnotationModel;
+import org.eclipse.jface.text.source.projection.ProjectionSupport;
+import org.eclipse.jface.text.source.projection.ProjectionViewer;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.editors.text.TextEditor;
+import org.eclipse.ui.texteditor.ChainedPreferenceStore;
+import org.eclipse.ui.texteditor.IDocumentProvider;
+import org.eclipse.ui.texteditor.SourceViewerDecorationSupport;
+import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
+
+/**
+ * The Acceleo template editor (Acceleo editor).
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class AcceleoEditor extends TextEditor implements IResourceChangeListener {
+
+ /**
+ * The Acceleo editor ID.
+ */
+ public static final String ACCELEO_EDITOR_ID = "org.eclipse.acceleo.ide.ui.editors.template.AcceleoEditor"; //$NON-NLS-1$
+
+ /**
+ * Preference key for matching brackets.
+ */
+ private static final String MATCHING_BRACKETS = PreferenceConstants.EDITOR_MATCHING_BRACKETS;
+
+ /**
+ * Preference key for matching brackets color.
+ */
+ private static final String MATCHING_BRACKETS_COLOR = PreferenceConstants.EDITOR_MATCHING_BRACKETS_COLOR;
+
+ /**
+ * The source content (The semantic content for this editor). It is used to create a CST model and is able
+ * to do an incremental parsing of the text.
+ */
+ private AcceleoSourceContent content;
+
+ /**
+ * Color manager for the syntax highlighting of this editor.
+ */
+ private ColorManager colorManager;
+
+ /**
+ * Content outline page.
+ */
+ private AcceleoOutlinePage contentOutlinePage;
+
+ /**
+ * A listener which is notified when the outline's selection changes.
+ */
+ private ISelectionChangedListener selectionChangedListener;
+
+ /**
+ * The editor's blocks matcher.
+ */
+ private AcceleoPairMatcher blockMatcher;
+
+ /** Allows us to enable folding support on this editor. */
+ private ProjectionSupport projectionSupport;
+
+ /** This will allow us to update the folding strucutre of the document. */
+ private ProjectionAnnotationModel annotationModel;
+
+ /**
+ * Keeps a reference to the object last updated in the outline through a double-click on the editor. This
+ * allows us to ignore the feedback &quot;updateSelection&quot; event from the outline.
+ */
+ private EObject updatingOutline;
+
+ /**
+ * Constructor.
+ */
+ public AcceleoEditor() {
+ super();
+ content = new AcceleoSourceContent();
+ colorManager = new ColorManager();
+ blockMatcher = new AcceleoPairMatcher(this);
+ }
+
+ /**
+ * Gets the source content. It stores the CST model that represents the semantic content of the text.
+ *
+ * @return the source content
+ */
+ public AcceleoSourceContent getContent() {
+ return content;
+ }
+
+ /**
+ * Gets the color manager. It is often used for syntax highlighting.
+ *
+ * @return the color manager
+ */
+ public ColorManager getColorManager() {
+ return colorManager;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.ui.editors.text.TextEditor#doSetInput(org.eclipse.ui.IEditorInput)
+ */
+ @Override
+ protected void doSetInput(IEditorInput input) throws CoreException {
+ setSourceViewerConfiguration(createSourceViewerConfiguration());
+ setDocumentProvider(createDocumentProvider());
+ super.doSetInput(input);
+ IDocumentProvider provider = getDocumentProvider();
+ if (provider != null) {
+ IFile file = getFile();
+ IDocument document = provider.getDocument(getEditorInput());
+ initializeContent(document, file);
+ }
+ }
+
+ /**
+ * Initializes the semantic content of the file, by creating the initial version of the CST model.
+ *
+ * @param document
+ * is the document
+ * @param file
+ * is the file
+ */
+ private void initializeContent(IDocument document, IFile file) {
+ if (document != null && file != null) {
+ try {
+ if (file.getProject().hasNature(AcceleoNature.NATURE_ID)) {
+ content.init(new StringBuffer(document.get()), file);
+ content.createCST();
+ } else {
+ MessageDialog.openError(getSite().getShell(), AcceleoUIMessages
+ .getString("AcceleoEditor.MissingNatureTitle"), //$NON-NLS-1$
+ AcceleoUIMessages.getString("AcceleoEditor.MissingNatureDescription")); //$NON-NLS-1$
+ content.init(new StringBuffer(document.get()), file);
+ content.createCST();
+ }
+ } catch (CoreException e) {
+ AcceleoUIActivator.getDefault().getLog().log(
+ new Status(IStatus.ERROR, AcceleoUIActivator.PLUGIN_ID, e.getMessage(), e));
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#initializeKeyBindingScopes()
+ */
+ @Override
+ protected void initializeKeyBindingScopes() {
+ setKeyBindingScopes(new String[] {"org.eclipse.acceleo.ide.ui.editors.template.editor"}); //$NON-NLS-1$
+ }
+
+ /**
+ * Creates the source viewer configuration.
+ *
+ * @return the source viewer configuration
+ */
+ protected SourceViewerConfiguration createSourceViewerConfiguration() {
+ return new AcceleoConfiguration(this, getPreferenceStore());
+ }
+
+ /**
+ * Creates the document provider.
+ *
+ * @return the document provider
+ */
+ protected IDocumentProvider createDocumentProvider() {
+ return new AcceleoDocumentProvider(this);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.ui.editors.text.TextEditor#dispose()
+ */
+ @Override
+ public void dispose() {
+ super.dispose();
+ colorManager.dispose();
+ getContentOutlinePage().removeSelectionChangedListener(selectionChangedListener);
+ ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
+ /*
+ * Dispose the block matcher
+ */
+ if (blockMatcher != null) {
+ blockMatcher.dispose();
+ blockMatcher = null;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.ui.editors.text.TextEditor#getAdapter(java.lang.Class)
+ */
+ @Override
+ @SuppressWarnings("unchecked")
+ public Object getAdapter(Class type) {
+ if (type.equals(IContentOutlinePage.class)) {
+ return getContentOutlinePage();
+ }
+ return super.getAdapter(type);
+ }
+
+ /**
+ * Returns the template content outline page. Creates the listener which is notified when the outline's
+ * selection changes.
+ *
+ * @return the template content outline page
+ */
+ protected AcceleoOutlinePage getContentOutlinePage() {
+ if (contentOutlinePage == null) {
+ contentOutlinePage = createContentOutlinePage();
+ selectionChangedListener = createSelectionChangeListener();
+ contentOutlinePage.addSelectionChangedListener(selectionChangedListener);
+ ResourcesPlugin.getWorkspace().addResourceChangeListener(this);
+ }
+ return contentOutlinePage;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.core.resources.IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent)
+ */
+ public void resourceChanged(final IResourceChangeEvent event) {
+ if (PlatformUI.getWorkbench().getActiveWorkbenchWindow() != null
+ && PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage() != null
+ && PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor() != this) {
+ if (event.getType() == IResourceChangeEvent.POST_CHANGE
+ && deltaMembers(event.getDelta()).contains(getFile())) {
+ try {
+ init(getEditorSite(), getEditorInput());
+ } catch (PartInitException e) {
+ AcceleoUIActivator.getDefault().getLog().log(
+ new Status(IStatus.ERROR, AcceleoUIActivator.PLUGIN_ID, e.getMessage(), e));
+ }
+ }
+ }
+ }
+
+ /**
+ * Gets all the modified files in the resource delta.
+ *
+ * @param delta
+ * the resource delta represents changes in the state of a resource tree
+ * @return all the modified files
+ */
+ private List<IFile> deltaMembers(IResourceDelta delta) {
+ List<IFile> files = new ArrayList<IFile>();
+ IResource resource = delta.getResource();
+ if (resource instanceof IFile) {
+ if (delta.getKind() == IResourceDelta.CHANGED) {
+ files.add((IFile)resource);
+ }
+ }
+ IResourceDelta[] children = delta.getAffectedChildren();
+ for (int i = 0; i < children.length; i++) {
+ files.addAll(deltaMembers(children[i]));
+ }
+ return files;
+ }
+
+ /**
+ * Creates the content outline page.
+ *
+ * @return the content outline page
+ */
+ protected AcceleoOutlinePage createContentOutlinePage() {
+ return new AcceleoOutlinePage(this);
+ }
+
+ /**
+ * Creates a listener which is notified when the outline's selection changes.
+ *
+ * @return the listener which is notified when the outline's selection changes
+ */
+ protected ISelectionChangedListener createSelectionChangeListener() {
+ return new ISelectionChangedListener() {
+ public void selectionChanged(SelectionChangedEvent event) {
+ selectionChangedDetected(event);
+ }
+ };
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#configureSourceViewerDecorationSupport(org.eclipse.ui.texteditor.SourceViewerDecorationSupport)
+ */
+ @Override
+ protected void configureSourceViewerDecorationSupport(SourceViewerDecorationSupport support) {
+ /*
+ * Set the block matcher
+ */
+ support.setCharacterPairMatcher(blockMatcher);
+ support.setMatchingCharacterPainterPreferenceKeys(MATCHING_BRACKETS, MATCHING_BRACKETS_COLOR);
+ // TODO it was JavaPlugin.getDefault().getPreferenceStore()
+ IPreferenceStore pref = AcceleoUIActivator.getDefault().getPreferenceStore();
+ IPreferenceStore[] stores = {getPreferenceStore(), pref};
+ setPreferenceStore(new ChainedPreferenceStore(stores));
+ support.install(getPreferenceStore());
+ super.configureSourceViewerDecorationSupport(support);
+ }
+
+ /**
+ * Methods which is notified when the outline's selection changes.
+ *
+ * @param event
+ * is the selection changed event
+ */
+ protected void selectionChangedDetected(SelectionChangedEvent event) {
+ ISelection selection = event.getSelection();
+ Object selectedElement = ((IStructuredSelection)selection).getFirstElement();
+ if (selectedElement == updatingOutline) {
+ // Simply ignore the event
+ updatingOutline = null;
+ } else if (selectedElement instanceof CSTNode) {
+ int b = ((CSTNode)selectedElement).getStartPosition();
+ int e = ((CSTNode)selectedElement).getEndPosition();
+ if (b > -1 && e > -1) {
+ selectRange(b, e);
+ }
+ }
+ }
+
+ /**
+ * Updates the outline selection by using the current offset in the text. It browses the CST model to find
+ * the element that is defined at the given offset.
+ *
+ * @param posBegin
+ * is the beginning index of the selected text
+ * @param posEnd
+ * is the ending index of the selected text
+ */
+ public void updateSelection(int posBegin, int posEnd) {
+ int e;
+ if (posEnd < posBegin) {
+ e = posBegin;
+ } else {
+ e = posEnd;
+ }
+ if (getContentOutlinePage() != null && posBegin > -1 && e > -1) {
+ // EObject
+ AcceleoSourceContent source = getContent();
+ if (source != null) {
+ EObject object = source.getCSTNode(posBegin, e);
+ if (object != null) {
+ updatingOutline = object;
+ getContentOutlinePage().setSelection(new StructuredSelection(object));
+ }
+ }
+ }
+ }
+
+ /**
+ * Sets the highlighted range of this text editor to the specified region.
+ *
+ * @param begin
+ * is the beginning index
+ * @param end
+ * is the ending index
+ */
+ protected void selectRange(int begin, int end) {
+ if (begin > -1 && end >= begin) {
+ ISourceViewer viewer = getSourceViewer();
+ StyledText widget = viewer.getTextWidget();
+ widget.setRedraw(false);
+ setHighlightRange(begin, end - begin, true);
+ selectAndReveal(begin, end - begin);
+ widget.setRedraw(true);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.ui.texteditor.AbstractTextEditor#doSave(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ @Override
+ public void doSave(IProgressMonitor progressMonitor) {
+ super.doSave(progressMonitor);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.ui.texteditor.AbstractTextEditor#doSaveAs()
+ */
+ @Override
+ public void doSaveAs() {
+ super.doSaveAs();
+ }
+
+ /**
+ * Get the input file for this editor.
+ *
+ * @return the editor input file
+ */
+ public IFile getFile() {
+ return (IFile)getEditorInput().getAdapter(IFile.class);
+ }
+
+ /**
+ * Updates the folding structure of the template. This will be called from the Acceleo template reconciler in
+ * order to allow the folding of blocks to the user.
+ *
+ * @param addedAnnotations
+ * These annotations have been added since the last reconciling operation.
+ * @param deletedAnnotations
+ * This list represents the annotations that were deleted since we last reconciled.
+ * @param modifiedAnnotations
+ * These annotations have seen their positions updated.
+ */
+ public void updateFoldingStructure(Map<Annotation, Position> addedAnnotations,
+ List<Annotation> deletedAnnotations, Map<Annotation, Position> modifiedAnnotations) {
+ Annotation[] deleted = new Annotation[deletedAnnotations.size()];
+ for (int i = 0; i < deletedAnnotations.size(); i++) {
+ deleted[i] = deletedAnnotations.get(i);
+ }
+ annotationModel.modifyAnnotations(deleted, addedAnnotations, null);
+ for (Map.Entry<Annotation, Position> entry : modifiedAnnotations.entrySet()) {
+ annotationModel.modifyAnnotationPosition(entry.getKey(), entry.getValue());
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#createPartControl(org.eclipse.swt.widgets.Composite)
+ */
+ @Override
+ public void createPartControl(Composite parent) {
+ super.createPartControl(parent);
+ ProjectionViewer viewer = (ProjectionViewer)getSourceViewer();
+
+ projectionSupport = new ProjectionSupport(viewer, getAnnotationAccess(), getSharedColors());
+ projectionSupport.install();
+
+ // turn projection mode on
+ viewer.doOperation(ProjectionViewer.TOGGLE);
+
+ annotationModel = viewer.getProjectionAnnotationModel();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#createSourceViewer(org.eclipse.swt.widgets.Composite,
+ * org.eclipse.jface.text.source.IVerticalRuler, int)
+ */
+ @Override
+ protected ISourceViewer createSourceViewer(Composite parent, IVerticalRuler ruler, int styles) {
+ ISourceViewer viewer = new ProjectionViewer(parent, ruler, getOverviewRuler(),
+ isOverviewRulerVisible(), styles);
+
+ // ensure decoration support has been created and configured.
+ getSourceViewerDecorationSupport(viewer);
+
+ return viewer;
+ }
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoEditorActionContributor.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoEditorActionContributor.java
new file mode 100644
index 0000000..5594e49
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoEditorActionContributor.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.editors.template;
+
+import org.eclipse.acceleo.internal.ide.ui.editors.template.actions.CommentAction;
+import org.eclipse.acceleo.internal.ide.ui.editors.template.actions.OpenDeclarationAction;
+import org.eclipse.acceleo.internal.ide.ui.editors.template.actions.references.ReferencesSearchAction;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.texteditor.BasicTextEditorActionContributor;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+/**
+ * Contributes global actions for the Acceleo template editor.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class AcceleoEditorActionContributor extends BasicTextEditorActionContributor {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.ui.texteditor.BasicTextEditorActionContributor#setActiveEditor(org.eclipse.ui.IEditorPart)
+ */
+ public void setActiveEditor(IEditorPart part) {
+ super.setActiveEditor(part);
+ if (!(part instanceof ITextEditor)) {
+ return;
+ }
+ IActionBars actionBars = getActionBars();
+ if (actionBars == null) {
+ return;
+ }
+ OpenDeclarationAction openAction = new OpenDeclarationAction();
+ openAction.setActionDefinitionId(OpenDeclarationAction.ACTION_ID);
+ actionBars.setGlobalActionHandler(OpenDeclarationAction.COMMAND_ID, openAction);
+
+ ReferencesSearchAction referencesSearchAction = new ReferencesSearchAction();
+ referencesSearchAction.setActionDefinitionId(ReferencesSearchAction.ACTION_ID);
+ actionBars.setGlobalActionHandler(ReferencesSearchAction.COMMAND_ID, referencesSearchAction);
+
+ CommentAction commentAction = new CommentAction();
+ commentAction.setActionDefinitionId(CommentAction.ACTION_ID);
+ actionBars.setGlobalActionHandler(CommentAction.COMMAND_ID, commentAction);
+ }
+
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoElementHyperlinkDetector.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoElementHyperlinkDetector.java
new file mode 100644
index 0000000..9121716
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoElementHyperlinkDetector.java
@@ -0,0 +1,184 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.editors.template;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.acceleo.internal.ide.ui.AcceleoUIMessages;
+import org.eclipse.acceleo.internal.ide.ui.editors.template.utils.OpenDeclarationUtils;
+import org.eclipse.acceleo.parser.cst.CSTNode;
+import org.eclipse.emf.common.notify.AdapterFactory;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
+import org.eclipse.emf.edit.provider.IItemLabelProvider;
+import org.eclipse.emf.edit.provider.ReflectiveItemProviderAdapterFactory;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.hyperlink.AbstractHyperlinkDetector;
+import org.eclipse.jface.text.hyperlink.IHyperlink;
+import org.eclipse.ocl.utilities.ASTNode;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+/**
+ * This will allow us to plug the CTRL+click "open declaration" in Acceleo editors.
+ *
+ * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
+ */
+public class AcceleoElementHyperlinkDetector extends AbstractHyperlinkDetector {
+ /** Adapter factory instance. This contains all factories registered in the global registry. */
+ private static final ComposedAdapterFactory FACTORY = createAdapterFactory();
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.jface.text.hyperlink.IHyperlinkDetector#detectHyperlinks(org.eclipse.jface.text.ITextViewer,
+ * org.eclipse.jface.text.IRegion, boolean)
+ */
+ public IHyperlink[] detectHyperlinks(ITextViewer textViewer, IRegion region,
+ boolean canShowMultipleHyperlinks) {
+ final ITextEditor textEditor = (ITextEditor)getAdapter(ITextEditor.class);
+ if (region == null || !(textEditor instanceof AcceleoEditor)) {
+ return null;
+ }
+
+ EObject res = null;
+ final AcceleoEditor editor = (AcceleoEditor)textEditor;
+ int offset = region.getOffset();
+
+ ASTNode astNode = editor.getContent().getASTNode(offset, offset);
+ if (astNode != null) {
+ res = OpenDeclarationUtils.findDeclarationFromAST(astNode);
+ }
+ if (res == null) {
+ CSTNode cstNode = editor.getContent().getCSTNode(offset, offset);
+ if (cstNode != null) {
+ res = OpenDeclarationUtils.findDeclarationFromCST(editor, astNode, cstNode);
+ }
+ }
+ IHyperlink[] links = null;
+ if (res != null) {
+ links = new IHyperlink[1];
+ links[0] = new AcceleoElementHyperlink(editor, region, res);
+ }
+ return links;
+ }
+
+ /**
+ * Returns an adapter factory containing all the global EMF registry's factories.
+ *
+ * @return An adapter factory made of all the adapter factories declared in the registry.
+ */
+ private static ComposedAdapterFactory createAdapterFactory() {
+ final List<AdapterFactory> factories = new ArrayList<AdapterFactory>();
+ factories.add(new ComposedAdapterFactory(ComposedAdapterFactory.Descriptor.Registry.INSTANCE));
+ factories.add(new ReflectiveItemProviderAdapterFactory());
+ return new ComposedAdapterFactory(factories);
+ }
+
+ /**
+ * This will try and get the IItemLabelProvider associated to the given EObject if its ItemProviderFactory
+ * is registered, then return the text it provides.
+ *
+ * @param eObj
+ * EObject we need the text of.
+ * @return The text provided by the IItemLabelProvider associated with <tt>eObj</tt>, <code>null</code> if
+ * it cannot be found.
+ * @see IItemLabelProvider#getText(Object)
+ * @since 0.8
+ */
+ protected static String getLabelFor(EObject eObj) {
+ final String text;
+ if (eObj == null) {
+ text = "null"; //$NON-NLS-1$
+ } else {
+ final IItemLabelProvider labelProvider = (IItemLabelProvider)FACTORY.adapt(eObj,
+ IItemLabelProvider.class);
+ if (labelProvider != null) {
+ text = labelProvider.getText(eObj);
+ } else {
+ text = ""; //$NON-NLS-1$
+ }
+ }
+ return text;
+ }
+
+ /**
+ * This implementation of an hyperlink allows for the opening of Acceleo elements declarations.
+ *
+ * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
+ */
+ private class AcceleoElementHyperlink implements IHyperlink {
+ /** Region of this hyperlink. */
+ private final IRegion hyperLinkRegion;
+
+ /** EObject that will be opened via this hyperlink. */
+ private final EObject target;
+
+ /** Editor on which this link appears. */
+ private final ITextEditor sourceEditor;
+
+ /**
+ * Instantiates an Acceleo hyperlink given the editor it appears on, the text region it spans to, and the
+ * link's target.
+ *
+ * @param editor
+ * Editor on which this hyperlink is shown.
+ * @param region
+ * Region of the editor where this hyperlink appears.
+ * @param linkTarget
+ * Target of the hyperlink.
+ */
+ public AcceleoElementHyperlink(ITextEditor editor, IRegion region, EObject linkTarget) {
+ sourceEditor = editor;
+ hyperLinkRegion = region;
+ target = linkTarget;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.jface.text.hyperlink.IHyperlink#getHyperlinkRegion()
+ */
+ public IRegion getHyperlinkRegion() {
+ return hyperLinkRegion;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.jface.text.hyperlink.IHyperlink#getHyperlinkText()
+ */
+ public String getHyperlinkText() {
+ return AcceleoUIMessages.getString("AcceleoElementHyperlinkDetector.OpenDeclarationLabel", //$NON-NLS-1$
+ getLabelFor(target));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.jface.text.hyperlink.IHyperlink#getTypeLabel()
+ */
+ public String getTypeLabel() {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.jface.text.hyperlink.IHyperlink#open()
+ */
+ public void open() {
+ OpenDeclarationUtils.showEObject(sourceEditor.getSite().getPage(), target.eResource().getURI(),
+ OpenDeclarationUtils.createRegion(target), target);
+ }
+ }
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoHover.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoHover.java
new file mode 100644
index 0000000..d6e5c85
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoHover.java
@@ -0,0 +1,139 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.editors.template;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.acceleo.ide.ui.AcceleoUIActivator;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.IAnnotationHover;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.ui.texteditor.MarkerAnnotation;
+
+/**
+ * Text hover for an annotation in the template editor.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class AcceleoHover implements IAnnotationHover {
+
+ /**
+ * The template editor.
+ */
+ protected AcceleoEditor editor;
+
+ /**
+ * Constructor.
+ *
+ * @param editor
+ * is the editor
+ */
+ public AcceleoHover(AcceleoEditor editor) {
+ this.editor = editor;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.jface.text.source.IAnnotationHover#getHoverInfo(org.eclipse.jface.text.source.ISourceViewer,
+ * int)
+ */
+ public String getHoverInfo(ISourceViewer sourceViewer, int lineNumber) {
+ return getHoverText(sourceViewer.getAnnotationModel(), sourceViewer.getDocument(), lineNumber);
+ }
+
+ /**
+ * Hover text for an annotation at the given line.
+ *
+ * @param model
+ * is the annotation model
+ * @param document
+ * is the current document
+ * @param lineNumber
+ * is the line number
+ * @return hover text of the annotation
+ */
+ protected String getHoverText(IAnnotationModel model, IDocument document, int lineNumber) {
+ StringBuffer text = null;
+ Iterator<Annotation> annotations = findAnnotations(model, document, lineNumber).iterator();
+ while (annotations.hasNext()) {
+ Annotation annotation = annotations.next();
+ String msg = null;
+ if (annotation instanceof MarkerAnnotation) {
+ try {
+ msg = (String)((MarkerAnnotation)annotation).getMarker().getAttribute(IMarker.MESSAGE);
+ } catch (CoreException e) {
+ AcceleoUIActivator.getDefault().getLog().log(
+ new Status(IStatus.ERROR, AcceleoUIActivator.PLUGIN_ID, e.getMessage(), e));
+ }
+ }
+ if (msg != null) {
+ if (text == null) {
+ text = new StringBuffer(msg);
+ } else {
+ text.append('\n');
+ text.append(msg);
+ }
+ }
+ }
+ if (text != null) {
+ return text.toString();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Returns all the annotations at the given line.
+ *
+ * @param model
+ * is the annotation model
+ * @param document
+ * is the current document
+ * @param lineNumber
+ * is the line number
+ * @return all the annotations
+ */
+ private List<Annotation> findAnnotations(IAnnotationModel model, IDocument document, int lineNumber) {
+ List<Annotation> annotations = new ArrayList<Annotation>();
+ IAnnotationModel annotationModel;
+ if (model == null && editor != null) {
+ annotationModel = editor.getDocumentProvider().getAnnotationModel(editor.getEditorInput());
+ } else {
+ annotationModel = model;
+ }
+ if (annotationModel != null) {
+ for (Iterator<?> it = annotationModel.getAnnotationIterator(); it.hasNext();) {
+ Annotation annotation = (Annotation)it.next();
+ Position position = annotationModel.getPosition(annotation);
+ try {
+ if (document != null && document.getLineOfOffset(position.offset) == lineNumber) {
+ annotations.add(annotation);
+ }
+ } catch (BadLocationException e) {
+ // continue
+ }
+ }
+ }
+ return annotations;
+ }
+
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoOutlinePage.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoOutlinePage.java
new file mode 100644
index 0000000..d4b6a65
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoOutlinePage.java
@@ -0,0 +1,147 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.editors.template;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import org.eclipse.acceleo.parser.cst.Module;
+import org.eclipse.emf.common.command.BasicCommandStack;
+import org.eclipse.emf.common.notify.AdapterFactory;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.provider.EcoreItemProviderAdapterFactory;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
+import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
+import org.eclipse.emf.edit.provider.ReflectiveItemProviderAdapterFactory;
+import org.eclipse.emf.edit.provider.resource.ResourceItemProviderAdapterFactory;
+import org.eclipse.jface.viewers.TreePath;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.views.contentoutline.ContentOutlinePage;
+
+/**
+ * The template content outline page. This content outline page will be presented to the user via the standard
+ * Content Outline View (the user decides whether their workbench window contains this view) whenever that
+ * source editor is active.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class AcceleoOutlinePage extends ContentOutlinePage {
+
+ /**
+ * The editor.
+ */
+ protected AcceleoEditor editor;
+
+ /**
+ * The factory for creating adapters.
+ */
+ protected AdapterFactory adapterFactory;
+
+ /**
+ * The editing domain.
+ */
+ protected AdapterFactoryEditingDomain editingDomain;
+
+ /**
+ * The item provider of the outline page.
+ */
+ protected AcceleoOutlinePageItemProviderAdapterFactory outlinePageItemProvider;
+
+ /**
+ * Constructor.
+ *
+ * @param editor
+ * is the editor
+ */
+ public AcceleoOutlinePage(AcceleoEditor editor) {
+ super();
+ this.editor = editor;
+ outlinePageItemProvider = new AcceleoOutlinePageItemProviderAdapterFactory(editor);
+ List<AdapterFactory> factories = new ArrayList<AdapterFactory>();
+ factories.add(outlinePageItemProvider);
+ factories.add(new ResourceItemProviderAdapterFactory());
+ factories.add(new EcoreItemProviderAdapterFactory());
+ factories.add(new ReflectiveItemProviderAdapterFactory());
+ adapterFactory = new ComposedAdapterFactory(factories);
+ BasicCommandStack commandStack = new BasicCommandStack();
+ editingDomain = new AdapterFactoryEditingDomain(adapterFactory, commandStack,
+ new HashMap<Resource, Boolean>());
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.ui.views.contentoutline.ContentOutlinePage#createControl(org.eclipse.swt.widgets.Composite)
+ */
+ @Override
+ public void createControl(Composite parent) {
+ super.createControl(parent);
+ TreeViewer viewer = getTreeViewer();
+ viewer.setContentProvider(new AcceleoOutlinePageContentProvider(adapterFactory));
+ viewer.setLabelProvider(new AcceleoOutlinePageLabelProvider(adapterFactory));
+ setInput(editor.getContent().getCST());
+ }
+
+ /**
+ * Updates the input model of the outline view.
+ *
+ * @param root
+ * is the root element of the new input model
+ */
+ private void setInput(EObject root) {
+ if (root != null && root.eContents().size() > 0) {
+ if (root.eContents().size() == 1) {
+ getTreeViewer().setInput((root.eContents().get(0)).eContents());
+ } else {
+ getTreeViewer().setInput(root.eContents());
+ }
+ } else {
+ getTreeViewer().setInput(null);
+ }
+ }
+
+ /**
+ * Refreshes the given element and its children in the outline view.
+ *
+ * @param element
+ * is the element to refresh
+ */
+ public void refresh(final Object element) {
+ if (element instanceof EObject && ((EObject)element).eContainer() != null) {
+ refreshContainer(((EObject)element).eContainer());
+ } else {
+ refreshContainer(element);
+ }
+ getTreeViewer().expandToLevel(element, 2);
+ }
+
+ /**
+ * Refreshes the given container and its children in the outline view.
+ *
+ * @param element
+ * is the container of the modified element
+ */
+ private void refreshContainer(final Object element) {
+ if (element instanceof Module) {
+ getTreeViewer().setInput(element);
+ } else {
+ Object[] elements = getTreeViewer().getExpandedElements();
+ TreePath[] treePaths = getTreeViewer().getExpandedTreePaths();
+ getTreeViewer().refresh();
+ getTreeViewer().setExpandedElements(elements);
+ getTreeViewer().setExpandedTreePaths(treePaths);
+ }
+ }
+
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoOutlinePageContentProvider.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoOutlinePageContentProvider.java
new file mode 100644
index 0000000..39b063e
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoOutlinePageContentProvider.java
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.editors.template;
+
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.eclipse.acceleo.parser.cst.CSTNode;
+import org.eclipse.emf.common.notify.AdapterFactory;
+import org.eclipse.emf.edit.ui.provider.AdapterFactoryContentProvider;
+
+/**
+ * The content provider used to show the CST objects in the outline view.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class AcceleoOutlinePageContentProvider extends AdapterFactoryContentProvider {
+
+ /**
+ * Constructor.
+ *
+ * @param adapterFactory
+ * is the adapter factory
+ */
+ public AcceleoOutlinePageContentProvider(AdapterFactory adapterFactory) {
+ super(adapterFactory);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.emf.edit.ui.provider.AdapterFactoryContentProvider#getElements(java.lang.Object)
+ */
+ @SuppressWarnings("unchecked")
+ public Object[] getElements(Object object) {
+ if (object instanceof List) {
+ Set<CSTNode> orderedCollection = new TreeSet<CSTNode>(new Comparator<CSTNode>() {
+ public int compare(CSTNode n0, CSTNode n1) {
+ if (n0.getStartPosition() < n1.getStartPosition()) {
+ return -1;
+ } else {
+ return 1;
+ }
+ }
+ });
+ Iterator<Object> it = ((List)object).iterator();
+ while (it.hasNext()) {
+ Object element = it.next();
+ if (element instanceof CSTNode) {
+ orderedCollection.add((CSTNode)element);
+ }
+ }
+ return orderedCollection.toArray();
+ } else {
+ return super.getElements(object);
+ }
+ }
+
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoOutlinePageItemProvider.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoOutlinePageItemProvider.java
new file mode 100644
index 0000000..6b33bf1
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoOutlinePageItemProvider.java
@@ -0,0 +1,259 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.editors.template;
+
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.eclipse.acceleo.common.IAcceleoConstants;
+import org.eclipse.acceleo.ide.ui.AcceleoUIActivator;
+import org.eclipse.acceleo.internal.ide.ui.AcceleoUIMessages;
+import org.eclipse.acceleo.parser.cst.CSTNode;
+import org.eclipse.acceleo.parser.cst.Comment;
+import org.eclipse.acceleo.parser.cst.CstPackage;
+import org.eclipse.acceleo.parser.cst.Template;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.edit.provider.ReflectiveItemProvider;
+
+/**
+ * Specific item provider for the outline view.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class AcceleoOutlinePageItemProvider extends ReflectiveItemProvider {
+
+ /**
+ * Constructor.
+ *
+ * @param adapterFactory
+ * is the adapter factory
+ */
+ public AcceleoOutlinePageItemProvider(AcceleoOutlinePageItemProviderAdapterFactory adapterFactory) {
+ super(adapterFactory);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.emf.edit.provider.ReflectiveItemProvider#getImage(java.lang.Object)
+ */
+ @Override
+ public Object getImage(Object object) {
+ EObject eObject = (EObject)object;
+ if (eObject instanceof Template) {
+ boolean isMain = false;
+ Iterator<EObject> iChildren = eObject.eAllContents();
+ while (!isMain && iChildren.hasNext()) {
+ EObject iChild = iChildren.next();
+ if (iChild instanceof Comment && ((Comment)iChild).getBody() != null
+ && ((Comment)iChild).getBody().indexOf(IAcceleoConstants.TAG_MAIN) > -1) {
+ isMain = true;
+ }
+ }
+ if (isMain) {
+ return AcceleoUIActivator.getDefault().getImage("icons/template-editor/Template_main.gif"); //$NON-NLS-1$
+ }
+ }
+ return AcceleoUIActivator.getDefault().getImage(
+ "icons/template-editor/" + eObject.eClass().getName() + ".gif"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.emf.edit.provider.ReflectiveItemProvider#getText(java.lang.Object)
+ */
+ @Override
+ public String getText(Object object) {
+ StringBuffer text = new StringBuffer();
+ if (object instanceof EObject) {
+ EObject eObject = (EObject)object;
+ EClass eClass = eObject.eClass();
+ switch (eClass.getClassifierID()) {
+ case CstPackage.MODULE:
+ org.eclipse.acceleo.parser.cst.Module eModule = (org.eclipse.acceleo.parser.cst.Module)eObject;
+ text.append(eModule.getName());
+ break;
+ case CstPackage.MODULE_EXTENDS_VALUE:
+ org.eclipse.acceleo.parser.cst.ModuleExtendsValue eModuleExtendsValue = (org.eclipse.acceleo.parser.cst.ModuleExtendsValue)eObject;
+ text.append("extends "); //$NON-NLS-1$
+ text.append(eModuleExtendsValue.getName());
+ break;
+ case CstPackage.MODULE_IMPORTS_VALUE:
+ org.eclipse.acceleo.parser.cst.ModuleImportsValue eModuleImportsValue = (org.eclipse.acceleo.parser.cst.ModuleImportsValue)eObject;
+ text.append("import "); //$NON-NLS-1$
+ text.append(eModuleImportsValue.getName());
+ break;
+ case CstPackage.TYPED_MODEL:
+ org.eclipse.acceleo.parser.cst.TypedModel eTypedModel = (org.eclipse.acceleo.parser.cst.TypedModel)eObject;
+ text.append(getTextForTypedModel(eTypedModel));
+ break;
+ case CstPackage.COMMENT:
+ text.append("[comment/]"); //$NON-NLS-1$
+ break;
+ case CstPackage.TEMPLATE:
+ org.eclipse.acceleo.parser.cst.Template eTemplate = (org.eclipse.acceleo.parser.cst.Template)eObject;
+ text.append(getTextForTemplate(eTemplate));
+ break;
+ case CstPackage.TEMPLATE_OVERRIDES_VALUE:
+ org.eclipse.acceleo.parser.cst.TemplateOverridesValue eTemplateOverridesValue = (org.eclipse.acceleo.parser.cst.TemplateOverridesValue)eObject;
+ text.append("overrides "); //$NON-NLS-1$
+ text.append(eTemplateOverridesValue.getName());
+ break;
+ case CstPackage.VARIABLE:
+ org.eclipse.acceleo.parser.cst.Variable eVariable = (org.eclipse.acceleo.parser.cst.Variable)eObject;
+ text.append(getTextForVariable(eVariable));
+ break;
+ case CstPackage.TEMPLATE_EXPRESSION:
+ break;
+ case CstPackage.MODEL_EXPRESSION:
+ org.eclipse.acceleo.parser.cst.ModelExpression eModelExpression = (org.eclipse.acceleo.parser.cst.ModelExpression)eObject;
+ if (eModelExpression.getBody() != null) {
+ text.append(eModelExpression.getBody());
+ }
+ break;
+ case CstPackage.TEXT_EXPRESSION:
+ break;
+ case CstPackage.BLOCK:
+ break;
+ case CstPackage.INIT_SECTION:
+ text.append("{}"); //$NON-NLS-1$
+ break;
+ case CstPackage.PROTECTED_AREA_BLOCK:
+ text.append("[protected/]"); //$NON-NLS-1$
+ break;
+ case CstPackage.FOR_BLOCK:
+ text.append("[for/]"); //$NON-NLS-1$
+ break;
+ case CstPackage.IF_BLOCK:
+ text.append("[if/]"); //$NON-NLS-1$
+ break;
+ case CstPackage.LET_BLOCK:
+ text.append("[let/]"); //$NON-NLS-1$
+ break;
+ case CstPackage.FILE_BLOCK:
+ text.append("[file/]"); //$NON-NLS-1$
+ break;
+ case CstPackage.TRACE_BLOCK:
+ text.append("[trace/]"); //$NON-NLS-1$
+ break;
+ case CstPackage.MACRO:
+ org.eclipse.acceleo.parser.cst.Macro eMacro = (org.eclipse.acceleo.parser.cst.Macro)eObject;
+ text.append("macro " + eMacro.getName()); //$NON-NLS-1$
+ break;
+ case CstPackage.QUERY:
+ org.eclipse.acceleo.parser.cst.Query eQuery = (org.eclipse.acceleo.parser.cst.Query)eObject;
+ text.append("query " + eQuery.getName()); //$NON-NLS-1$
+ break;
+ default:
+ throw new IllegalArgumentException(AcceleoUIMessages.getString(
+ "AcceleoOutlinePageItemProvider.InvalidClassifier", eClass.getName())); //$NON-NLS-1$
+ }
+ }
+ return text.toString().trim();
+ }
+
+ /**
+ * Gets the label text specific to a 'TypedModel' instance.
+ *
+ * @param eTypedModel
+ * is the model object '<em><b>Typed Model</b></em>'.
+ * @return the text
+ */
+ private StringBuffer getTextForTypedModel(org.eclipse.acceleo.parser.cst.TypedModel eTypedModel) {
+ StringBuffer text = new StringBuffer();
+ text.append("model "); //$NON-NLS-1$
+ for (Iterator<EPackage> ePackages = eTypedModel.getTakesTypesFrom().iterator(); ePackages.hasNext();) {
+ text.append(ePackages.next().getName());
+ if (ePackages.hasNext()) {
+ text.append(" ,"); //$NON-NLS-1$
+ }
+ }
+ return text;
+ }
+
+ /**
+ * Gets the label text specific to a 'Template' instance.
+ *
+ * @param eTemplate
+ * is the model object '<em><b>Template</b></em>'.
+ * @return the text
+ */
+ private StringBuffer getTextForTemplate(org.eclipse.acceleo.parser.cst.Template eTemplate) {
+ StringBuffer text = new StringBuffer();
+ text.append("template "); //$NON-NLS-1$
+ text.append(eTemplate.getName());
+ text.append("("); //$NON-NLS-1$
+ for (Iterator<org.eclipse.acceleo.parser.cst.Variable> eParameters = eTemplate.getParameter().iterator(); eParameters
+ .hasNext();) {
+ org.eclipse.acceleo.parser.cst.Variable eVariable = eParameters.next();
+ if (eVariable.getType() != null) {
+ text.append(eVariable.getType());
+ }
+ if (eParameters.hasNext()) {
+ text.append(", "); //$NON-NLS-1$
+ }
+ }
+ text.append(")"); //$NON-NLS-1$
+ return text;
+ }
+
+ /**
+ * Gets the label text specific to a 'Variable' instance.
+ *
+ * @param eVariable
+ * is the model object '<em><b>Variable</b></em>'.
+ * @return the text
+ */
+ private StringBuffer getTextForVariable(org.eclipse.acceleo.parser.cst.Variable eVariable) {
+ StringBuffer text = new StringBuffer();
+ text.append(eVariable.getName());
+ text.append(":"); //$NON-NLS-1$
+ if (eVariable.getType() != null) {
+ text.append(eVariable.getType());
+ }
+ return text;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.emf.edit.provider.ItemProviderAdapter#getChildren(java.lang.Object)
+ */
+ @Override
+ public Collection<?> getChildren(Object object) {
+ Collection<?> children = super.getChildren(object);
+ Set<CSTNode> orderedCollection = new TreeSet<CSTNode>(new Comparator<CSTNode>() {
+ public int compare(CSTNode n0, CSTNode n1) {
+ if (n0.getStartPosition() < n1.getStartPosition()) {
+ return -1;
+ } else {
+ return 1;
+ }
+ }
+ });
+ Iterator<?> childrenIt = children.iterator();
+ while (childrenIt.hasNext()) {
+ Object next = childrenIt.next();
+ if (next instanceof org.eclipse.acceleo.parser.cst.TextExpression) {
+ continue;
+ } else {
+ orderedCollection.add((CSTNode)next);
+ }
+ }
+ return orderedCollection;
+ }
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoOutlinePageItemProviderAdapterFactory.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoOutlinePageItemProviderAdapterFactory.java
new file mode 100644
index 0000000..9acd654
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoOutlinePageItemProviderAdapterFactory.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.editors.template;
+
+import org.eclipse.emf.edit.provider.IEditingDomainItemProvider;
+import org.eclipse.emf.edit.provider.IItemLabelProvider;
+import org.eclipse.emf.edit.provider.IItemPropertySource;
+import org.eclipse.emf.edit.provider.IStructuredItemContentProvider;
+import org.eclipse.emf.edit.provider.ITableItemLabelProvider;
+import org.eclipse.emf.edit.provider.ITreeItemContentProvider;
+import org.eclipse.emf.edit.provider.ReflectiveItemProviderAdapterFactory;
+
+/**
+ * Specific item provider adapter factory for the outline of the template editor.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class AcceleoOutlinePageItemProviderAdapterFactory extends ReflectiveItemProviderAdapterFactory {
+
+ /**
+ * The template editor.
+ */
+ protected AcceleoEditor editor;
+
+ /**
+ * Constructor.
+ *
+ * @param editor
+ * is the editor
+ */
+ public AcceleoOutlinePageItemProviderAdapterFactory(AcceleoEditor editor) {
+ this.editor = editor;
+ reflectiveItemProviderAdapter = createReflectiveItemProvider();
+ supportedTypes.add(IStructuredItemContentProvider.class);
+ supportedTypes.add(ITreeItemContentProvider.class);
+ supportedTypes.add(IItemPropertySource.class);
+ supportedTypes.add(IEditingDomainItemProvider.class);
+ supportedTypes.add(IItemLabelProvider.class);
+ supportedTypes.add(ITableItemLabelProvider.class);
+ }
+
+ /**
+ * Gets template editor.
+ *
+ * @return the editor
+ */
+ public AcceleoEditor getSourceEditor() {
+ return editor;
+ }
+
+ /**
+ * Creates the specific item provider for the template editor.
+ *
+ * @return the item provider
+ */
+ protected AcceleoOutlinePageItemProvider createReflectiveItemProvider() {
+ return new AcceleoOutlinePageItemProvider(this);
+ }
+
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoOutlinePageLabelProvider.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoOutlinePageLabelProvider.java
new file mode 100644
index 0000000..15a2110
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoOutlinePageLabelProvider.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.editors.template;
+
+import org.eclipse.emf.common.notify.AdapterFactory;
+import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * The label provider for the objects shown in the outline view.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class AcceleoOutlinePageLabelProvider extends AdapterFactoryLabelProvider {
+
+ /**
+ * Constructor.
+ *
+ * @param adapterFactory
+ * is the adapter factory
+ */
+ public AcceleoOutlinePageLabelProvider(AdapterFactory adapterFactory) {
+ super(adapterFactory);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider#getImage(java.lang.Object)
+ */
+ public Image getImage(Object object) {
+ return super.getImage(object);
+ }
+
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoPairMatcher.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoPairMatcher.java
new file mode 100644
index 0000000..e03b73c
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoPairMatcher.java
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.editors.template;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.source.DefaultCharacterPairMatcher;
+
+/**
+ * Helper class for match pairs of special characters.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class AcceleoPairMatcher extends DefaultCharacterPairMatcher {
+
+ /**
+ * Blocks used by aggregated the matcher.
+ */
+ protected static final char[] BLOCKS = {'(', ')', '[', ']', '{', '}'};
+
+ /**
+ * The aggregated matcher, it is used for trivial block matching.
+ */
+ protected DefaultCharacterPairMatcher aggregatedMatcher;
+
+ /**
+ * Constructor.
+ *
+ * @param editor
+ * is the editor
+ */
+ public AcceleoPairMatcher(AcceleoEditor editor) {
+ super(new char[0]);
+ aggregatedMatcher = new DefaultCharacterPairMatcher(BLOCKS);
+
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.jface.text.source.DefaultCharacterPairMatcher#match(org.eclipse.jface.text.IDocument,
+ * int)
+ */
+ public IRegion match(IDocument document, int offset) {
+ try {
+ return performMatch(document, offset);
+ } catch (BadLocationException ble) {
+ return null;
+ }
+ }
+
+ /**
+ * Performs the actual work of matching for #match(IDocument, int).
+ *
+ * @param document
+ * is the document
+ * @param offset
+ * is the current offset
+ * @return the region
+ * @throws BadLocationException
+ * indicates the attempt to access a non-existing position
+ */
+ private IRegion performMatch(IDocument document, int offset) throws BadLocationException {
+ if (offset < 0 || document == null) {
+ return null;
+ }
+ return aggregatedMatcher.match(document, offset);
+ }
+
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoSourceContent.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoSourceContent.java
new file mode 100644
index 0000000..4320a9e
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoSourceContent.java
@@ -0,0 +1,942 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.editors.template;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.TreeSet;
+
+import org.eclipse.acceleo.common.IAcceleoConstants;
+import org.eclipse.acceleo.common.utils.ModelUtils;
+import org.eclipse.acceleo.ide.ui.AcceleoUIActivator;
+import org.eclipse.acceleo.ide.ui.resources.AcceleoProject;
+import org.eclipse.acceleo.internal.parser.ast.ocl.OCLParser;
+import org.eclipse.acceleo.internal.parser.cst.CSTParser;
+import org.eclipse.acceleo.parser.AcceleoSourceBuffer;
+import org.eclipse.acceleo.parser.cst.CSTNode;
+import org.eclipse.acceleo.parser.cst.CstFactory;
+import org.eclipse.acceleo.parser.cst.CstPackage;
+import org.eclipse.acceleo.parser.cst.ForBlock;
+import org.eclipse.acceleo.parser.cst.ModelExpression;
+import org.eclipse.acceleo.parser.cst.Module;
+import org.eclipse.acceleo.parser.cst.ModuleElement;
+import org.eclipse.acceleo.parser.cst.ModuleExtendsValue;
+import org.eclipse.acceleo.parser.cst.ModuleImportsValue;
+import org.eclipse.acceleo.parser.cst.Template;
+import org.eclipse.acceleo.parser.cst.TemplateExpression;
+import org.eclipse.acceleo.parser.cst.TemplateOverridesValue;
+import org.eclipse.acceleo.parser.cst.TextExpression;
+import org.eclipse.acceleo.parser.cst.Variable;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EClassifier;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EOperation;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.ocl.helper.Choice;
+import org.eclipse.ocl.helper.ChoiceKind;
+import org.eclipse.ocl.utilities.ASTNode;
+
+/**
+ * The source content (i.e the semantic content for the template editor). It can create a CST model and it is
+ * able to do an incremental parsing of the text. You have to initialize the content with the method
+ * <code>init</code>.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class AcceleoSourceContent {
+
+ /**
+ * Default URI of the EMTL file if it doesn't exist.
+ */
+ private static final String DEFAULT_EMTL_URI = "http://acceleo.eclipse.org/default.emtl"; //$NON-NLS-1$
+
+ /**
+ * The Acceleo file. It can be null if the file hasn't been specified.
+ */
+ private IFile file;
+
+ /**
+ * The Acceleo project which contains the Acceleo file. It can be null if the file hasn't been specified.
+ */
+ private AcceleoProject acceleoProject;
+
+ /**
+ * The source.
+ */
+ private AcceleoSourceBuffer source;
+
+ /**
+ * The parser used to create a CST model from the document.
+ */
+ private CSTParser cstParser;
+
+ /**
+ * Constructor.
+ */
+ public AcceleoSourceContent() {
+ }
+
+ /**
+ * Creates a specific Acceleo source buffer which is able to refresh the AST with a low priority job.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+ private class AcceleoSourceBufferWithASTJob extends AcceleoSourceBuffer {
+
+ /**
+ * The job to compute the AST.
+ */
+ private Job createASTJob;
+
+ /**
+ * Constructor.
+ *
+ * @param buffer
+ * is the buffer to parse, the file property will be null
+ */
+ public AcceleoSourceBufferWithASTJob(StringBuffer buffer) {
+ super(buffer);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.acceleo.parser.AcceleoSourceBuffer#refreshAST()
+ */
+ @Override
+ public void refreshAST() {
+ if (createASTJob != null) {
+ createASTJob.cancel();
+ }
+ createASTJob = createASTJob();
+ createASTJob.setPriority(Job.DECORATE);
+ createASTJob.schedule(1000);
+ }
+
+ /**
+ * Creates the job that is able to compute the AST.
+ *
+ * @return the job
+ */
+ private Job createASTJob() {
+ return new Job("Acceleo") { //$NON-NLS-1$
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ ast = null;
+ AcceleoSourceContent.this.createAST();
+ astCreator.canceling(false);
+ return new Status(IStatus.OK, AcceleoUIActivator.PLUGIN_ID, "OK"); //$NON-NLS-1$
+ }
+
+ @Override
+ protected void canceling() {
+ super.canceling();
+ astCreator.canceling(true);
+ }
+ };
+ }
+ }
+
+ /**
+ * Gets the current CST model. It creates the CST if <code>createCST</code> hasn't been called.
+ *
+ * @return the current CST model
+ */
+ public org.eclipse.acceleo.parser.cst.Module getCST() {
+ if (source == null) {
+ return null;
+ } else {
+ if (source.getCST() == null) {
+ createCST();
+ }
+ return source.getCST();
+ }
+ }
+
+ /**
+ * Gets the current AST model. It creates the AST if <code>createAST</code> hasn't been called.
+ *
+ * @return the current AST model
+ */
+ public org.eclipse.acceleo.model.mtl.Module getAST() {
+ if (source == null) {
+ return null;
+ } else {
+ if (source.getAST() == null) {
+ createAST();
+ }
+ return source.getAST();
+ }
+ }
+
+ /**
+ * Gets the Acceleo file. It can be null if the file hasn't been specified.
+ *
+ * @return the Acceleo file, or null
+ */
+ public IFile getFile() {
+ return file;
+ }
+
+ /**
+ * It initializes the template content with the given text. The file and the project won't be specified.
+ *
+ * @param text
+ * is the content of the document
+ */
+ public void init(StringBuffer text) {
+ init(text, null);
+ }
+
+ /**
+ * It initializes the template content with the given text and the corresponding file.
+ *
+ * @param text
+ * is the content of the document
+ * @param aFile
+ * is a file, can be null
+ */
+ public void init(StringBuffer text, IFile aFile) {
+ file = aFile;
+ if (file != null) {
+ acceleoProject = new AcceleoProject(file.getProject());
+ } else {
+ acceleoProject = null;
+ }
+ source = new AcceleoSourceBufferWithASTJob(text);
+ cstParser = new CSTParser(source);
+ }
+
+ /**
+ * Creates a CST model. You can get it with the method <code>getCST</code>.
+ */
+ public void createCST() {
+ source.createCST();
+ source.getProblems().clear();
+ }
+
+ /**
+ * Computes a delta version of the CST model, and returns the modified object. This object will be
+ * refreshed in the outline view.
+ *
+ * @param posBegin
+ * the beginning index, inclusive
+ * @param posEnd
+ * the ending index, exclusive
+ * @param newText
+ * the string that will replace previous contents
+ * @return the modified object
+ */
+ public CSTNode updateCST(int posBegin, int posEnd, String newText) {
+ source.getBuffer().replace(posBegin, posEnd, newText);
+ CSTNode current = getCSTNode(posBegin, posEnd);
+ if (current instanceof TextExpression && newText.indexOf(IAcceleoConstants.DEFAULT_BEGIN) > -1) {
+ current = (CSTNode)current.eContainer();
+ }
+ if (current != null && posBegin == posEnd && posBegin == current.getStartPosition()) {
+ if (!(current instanceof TextExpression || current instanceof Variable || current instanceof ModelExpression)) {
+ current = (CSTNode)current.eContainer();
+ }
+ }
+ while (current != null) {
+ EObject modified = null;
+ if (current instanceof ModuleElement
+ && ((ModuleElement)current).eContainingFeature() == CstPackage.eINSTANCE
+ .getModule_OwnedModuleElement()) {
+ ModuleElement oldModuleElement = (ModuleElement)current;
+ int newPosEnd = posBegin + newText.length();
+ int shift = newPosEnd - posEnd;
+ shiftPositionsAfter(posBegin, shift);
+ modified = replaceModuleElement(oldModuleElement);
+ if (modified == null) {
+ shiftPositionsAfter(posBegin + shift, -shift);
+ }
+ } else if (current instanceof ModelExpression) {
+ ModelExpression oldExpression = (ModelExpression)current;
+ int newPosEnd = posBegin + newText.length();
+ int shift = newPosEnd - posEnd;
+ shiftPositionsAfter(posBegin, shift);
+ modified = replaceModelExpression(oldExpression);
+ if (modified == null) {
+ shiftPositionsAfter(posBegin + shift, -shift);
+ }
+ } else if (current instanceof TemplateExpression) {
+ TemplateExpression oldExpression = (TemplateExpression)current;
+ int newPosEnd = posBegin + newText.length();
+ int shift = newPosEnd - posEnd;
+ shiftPositionsAfter(posBegin, shift);
+ modified = replaceTemplateExpression(oldExpression);
+ if (modified == null) {
+ shiftPositionsAfter(posBegin + shift, -shift);
+ }
+ } else if (current instanceof Variable) {
+ Variable oldVariable = (Variable)current;
+ int newPosEnd = posBegin + newText.length();
+ int shift = newPosEnd - posEnd;
+ shiftPositionsAfter(posBegin, shift);
+ modified = replaceVariable(oldVariable);
+ if (modified == null) {
+ shiftPositionsAfter(posBegin + shift, -shift);
+ }
+ }
+ if (modified instanceof CSTNode) {
+ source.refreshAST();
+ return (CSTNode)modified;
+ }
+ current = (CSTNode)current.eContainer();
+ }
+ source.createCST();
+ source.getProblems().clear();
+ source.refreshAST();
+ return source.getCST();
+ }
+
+ /**
+ * Creates a new version of a module element in the CST model.
+ *
+ * @param oldModuleElement
+ * is the old module element to replace
+ * @return the new module element
+ */
+ private EObject replaceModuleElement(ModuleElement oldModuleElement) {
+ Module tempModule = CstFactory.eINSTANCE.createModule();
+ if (getCST() != null) {
+ tempModule.getInput().addAll(EcoreUtil.copyAll(getCST().getInput()));
+ }
+ cstParser.parseModuleBody(oldModuleElement.getStartPosition(), oldModuleElement.getEndPosition(),
+ tempModule);
+ source.getProblems().clear();
+ if (tempModule.getOwnedModuleElement().size() > 0) {
+ try {
+ ModuleElement newModuleElement = tempModule.getOwnedModuleElement().get(0);
+ EcoreUtil.replace(oldModuleElement, newModuleElement);
+ return newModuleElement;
+ } catch (ClassCastException e) {
+ // continue
+ } catch (ArrayStoreException e) {
+ // continue
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Creates a new version of a model expression in the CST model.
+ *
+ * @param oldExpression
+ * is the old expression to replace
+ * @return the new model expression
+ */
+ private ModelExpression replaceModelExpression(ModelExpression oldExpression) {
+ oldExpression.setBefore(null);
+ oldExpression.setEach(null);
+ oldExpression.setAfter(null);
+ cstParser.getPBlock().parseExpressionHeader(oldExpression.getStartPosition(),
+ oldExpression.getEndPosition(), oldExpression);
+ source.getProblems().clear();
+ return oldExpression;
+ }
+
+ /**
+ * Creates a new version of a template expression in the CST model.
+ *
+ * @param oldExpression
+ * is the old expression to replace
+ * @return the new template expression
+ */
+ private EObject replaceTemplateExpression(TemplateExpression oldExpression) {
+ Module tempModule = CstFactory.eINSTANCE.createModule();
+ if (getCST() != null) {
+ tempModule.getInput().addAll(EcoreUtil.copyAll(getCST().getInput()));
+ }
+ Template tempBlock = CstFactory.eINSTANCE.createTemplate();
+ tempModule.getOwnedModuleElement().add(tempBlock);
+ cstParser.getPBlock().parse(oldExpression.getStartPosition(), oldExpression.getEndPosition(),
+ tempBlock);
+ source.getProblems().clear();
+ if (tempBlock.getBody().size() > 0) {
+ try {
+ TemplateExpression newExpression = tempBlock.getBody().get(0);
+ EcoreUtil.replace(oldExpression, newExpression);
+ return newExpression;
+ } catch (ClassCastException e) {
+ // continue
+ } catch (ArrayStoreException e) {
+ // continue
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Creates a new version of a variable in the CST model.
+ *
+ * @param oldVariable
+ * is the old variable to replace
+ * @return the new variable
+ */
+ private EObject replaceVariable(Variable oldVariable) {
+ Module tempModule = CstFactory.eINSTANCE.createModule();
+ if (getCST() != null) {
+ tempModule.getInput().addAll(EcoreUtil.copyAll(getCST().getInput()));
+ }
+ Variable newVariable = cstParser.createVariable(oldVariable.getStartPosition(), oldVariable
+ .getEndPosition(), tempModule);
+ source.getProblems().clear();
+ if (newVariable != null) {
+ try {
+ EcoreUtil.replace(oldVariable, newVariable);
+ return newVariable;
+ } catch (ClassCastException e) {
+ // continue
+ } catch (ArrayStoreException e) {
+ // continue
+ }
+ }
+ return null;
+ }
+
+ /**
+ * All the positions after the index are shifted. It browses the current CST and modifies the positions
+ * when it is necessary (only if pos > index).
+ *
+ * @param index
+ * is the beginning index for all the modifications
+ * @param shift
+ * is the value to be added for each position
+ */
+ private void shiftPositionsAfter(int index, int shift) {
+ if (getCST() != null) {
+ Iterator<EObject> eAllContents = getCST().eAllContents();
+ while (eAllContents.hasNext()) {
+ EObject eObject = eAllContents.next();
+ if (eObject instanceof CSTNode) {
+ CSTNode cstNode = (CSTNode)eObject;
+ shiftPositionsAfter(cstNode, index, shift);
+ }
+ }
+ }
+ }
+
+ /**
+ * The positions of the given CST candidate are shifted. It modifies the positions when it is necessary
+ * (only if pos > index).
+ *
+ * @param candidate
+ * is the current candidate to modify
+ * @param index
+ * is the beginning index for all the modifications
+ * @param shift
+ * is the value to be added for each position
+ */
+ private void shiftPositionsAfter(CSTNode candidate, int index, int shift) {
+ if (candidate instanceof TextExpression || candidate instanceof Variable
+ || candidate instanceof ModelExpression) {
+ if (candidate.getStartPosition() > index) {
+ assert candidate.getStartPosition() + shift > -1;
+ candidate.setStartPosition(candidate.getStartPosition() + shift);
+ }
+ if (candidate.getEndPosition() >= index) {
+ assert candidate.getEndPosition() + shift > -1;
+ candidate.setEndPosition(candidate.getEndPosition() + shift);
+ }
+ } else {
+ if (candidate.getStartPosition() >= index) {
+ assert candidate.getStartPosition() + shift > -1;
+ candidate.setStartPosition(candidate.getStartPosition() + shift);
+ }
+ if (candidate.getEndPosition() > index) {
+ assert candidate.getEndPosition() + shift > -1;
+ candidate.setEndPosition(candidate.getEndPosition() + shift);
+ }
+ }
+ }
+
+ /**
+ * Gets the nearest CST node at the given position.
+ *
+ * @param posBegin
+ * is the beginning index
+ * @param posEnd
+ * is the ending index
+ * @return the nearest CST node
+ */
+ public CSTNode getCSTNode(int posBegin, int posEnd) {
+ if (getCST() != null) {
+ CSTNode candidate = getCST();
+ CSTNode childrenCandidate = getChildrenCandidate(candidate, posBegin, posEnd);
+ while (childrenCandidate != null) {
+ candidate = childrenCandidate;
+ childrenCandidate = getChildrenCandidate(candidate, posBegin, posEnd);
+ }
+ return candidate;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Gets the nearest CST child at the given position. It browses the children of the given candidate and
+ * returns the nearest children if it exists.
+ *
+ * @param candidate
+ * is the current candidate to browse
+ * @param posBegin
+ * is the beginning index
+ * @param posEnd
+ * is the ending index
+ * @return the nearest CST node in the children of the current candidate
+ */
+ private CSTNode getChildrenCandidate(CSTNode candidate, int posBegin, int posEnd) {
+ Iterator<EObject> itContents = candidate.eContents().iterator();
+ while (itContents.hasNext()) {
+ CSTNode eContent = (CSTNode)itContents.next();
+ int startPosition = eContent.getStartPosition();
+ int endPosition = eContent.getEndPosition();
+ assert startPosition > -1 && endPosition > -1;
+ if (startPosition <= posBegin && endPosition >= posEnd) {
+ return eContent;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Gets the CST parent of the given type. It browses the ancestors of the given node and returns the
+ * nearest valid parent if it exists.
+ *
+ * @param node
+ * is the current node
+ * @param c
+ * is the class which represents the type of the parent to search
+ * @return the CST parent, or null if it doesn't exist
+ */
+ @SuppressWarnings("unchecked")
+ public CSTNode getCSTParent(CSTNode node, Class c) {
+ CSTNode eContainer = (CSTNode)node.eContainer();
+ while (eContainer != null) {
+ if (c.isInstance(eContainer)) {
+ return eContainer;
+ }
+ eContainer = (CSTNode)eContainer.eContainer();
+ }
+ return null;
+ }
+
+ /**
+ * Obtains syntax completion choices for the specified fragment of an OCL expression.
+ *
+ * @param text
+ * a partial OCL expression for which to seek choices that could be appended to it
+ * @param offset
+ * is the current offset in the text
+ * @return a list of {@link Choice}s, possibly empty. The ordering of the list may or may not indicate
+ * relative relevance or frequency of a choice
+ */
+ public synchronized Collection<Choice> getSyntaxHelp(String text, int offset) {
+ if (getCST() != null) {
+ org.eclipse.acceleo.model.mtl.Module vAST = source.getAST();
+ OCLParser oclParser;
+ if (vAST == null) {
+ createAST();
+ vAST = source.getAST();
+ }
+ if (vAST != null) {
+ URI uri = vAST.eResource().getURI();
+ vAST = (org.eclipse.acceleo.model.mtl.Module)EcoreUtil.copy(vAST);
+ ResourceSet resourceSet = new ResourceSetImpl();
+ Resource resource = resourceSet.createResource(uri);
+ resource.getContents().add(vAST);
+ oclParser = new OCLParser(resource);
+ List<URI> dependenciesURIs = getAccessibleOutputFiles();
+ loadImportsDependencies(vAST, dependenciesURIs);
+ loadExtendsDependencies(vAST, dependenciesURIs);
+ oclParser.addRecursivelyMetamodelsToScope(vAST);
+ boolean isAfterDot = isAfterDot(text);
+ oclParser.addRecursivelyBehavioralFeaturesToScope(vAST, true, !isAfterDot,
+ getCurrentQualifiedName(text));
+ int specificOffset = getSpecificOffset(offset);
+ EClassifier eContext = oclParser.addRecursivelyVariablesToScopeAndGetContextClassifierAt(
+ vAST, specificOffset);
+ if (eContext != null) {
+ oclParser.pushContext(eContext);
+ }
+ try {
+ return order(oclParser.getSyntaxHelp(text), oclParser);
+ } finally {
+ if (eContext != null) {
+ oclParser.popContext();
+ }
+ Iterator<Resource> resources = resourceSet.getResources().iterator();
+ while (resources.hasNext()) {
+ resources.next().unload();
+ }
+ }
+ }
+ }
+ return new ArrayList<Choice>();
+ }
+
+ /**
+ * Order a list of OCL completion proposals.
+ *
+ * @param choices
+ * is the list to order
+ * @param oclParser
+ * is the OCL parser used to get the given OCL choices
+ * @return an ordered list
+ */
+ private Collection<Choice> order(Collection<Choice> choices, OCLParser oclParser) {
+ Collection<Choice> orderedChoices = new TreeSet<Choice>(new Comparator<Choice>() {
+ public int compare(Choice arg0, Choice arg1) {
+ int value;
+ if (arg0.getKind() == ChoiceKind.VARIABLE && arg1.getKind() == ChoiceKind.VARIABLE) {
+ value = -1;
+ } else if (arg0.getKind() == ChoiceKind.VARIABLE) {
+ value = -1;
+ } else if (arg1.getKind() == ChoiceKind.VARIABLE) {
+ value = 1;
+ } else if (arg0.getKind() == ChoiceKind.PROPERTY && arg1.getKind() == ChoiceKind.PROPERTY) {
+ value = arg0.getName().compareTo(arg1.getName());
+ } else if (arg0 instanceof AcceleoCompletionChoice && !(arg1 instanceof AcceleoCompletionChoice)) {
+ value = -1;
+ } else if (arg0.getKind() == ChoiceKind.PROPERTY) {
+ value = -1;
+ } else {
+ value = 1;
+ }
+ return value;
+ }
+ });
+ Iterator<Choice> choicesIt = choices.iterator();
+ while (choicesIt.hasNext()) {
+ Choice choice = choicesIt.next();
+ if (choice.getElement() instanceof EOperation) {
+ EOperation eOperation = (EOperation)choice.getElement();
+ org.eclipse.acceleo.model.mtl.ModuleElement eModuleElement = oclParser.getModuleElement(eOperation);
+ if (eModuleElement != null) {
+ AcceleoCompletionChoice acceleoChoice = new AcceleoCompletionChoice(choice, eModuleElement);
+ choice = acceleoChoice;
+ }
+ }
+ orderedChoices.add(choice);
+ }
+ return orderedChoices;
+ }
+
+ /**
+ * Indicates if the beginning text of the completion is after a dot character.
+ *
+ * @param text
+ * is the beginning text
+ * @return true if the beginning text of the completion is after a dot character
+ */
+ private boolean isAfterDot(String text) {
+ boolean isAfterDot = false;
+ for (int i = text.length() - 1; !isAfterDot && i >= 0; i--) {
+ char c = text.charAt(i);
+ if (c == '.') {
+ isAfterDot = true;
+ } else if (!Character.isJavaIdentifierPart(c)) {
+ break;
+ }
+ }
+ return isAfterDot;
+ }
+
+ /**
+ * Gets the current name to filter during the completion, after a dot character...
+ *
+ * @param text
+ * is the beginning text
+ * @return the current name to filter
+ */
+ private String getCurrentQualifiedName(String text) {
+ StringBuffer result = new StringBuffer();
+ for (int i = text.length() - 1; i >= 0; i--) {
+ char c = text.charAt(i);
+ if (Character.isJavaIdentifierPart(c)) {
+ result.insert(0, c);
+ } else {
+ break;
+ }
+ }
+ return result.toString();
+ }
+
+ /**
+ * Gets a specific offset to ignore some variables in the current context.
+ * <p>
+ * The variable <b>classes</b> can't be used in the following example :
+ * </p>
+ * classes : Set(Class) = <b>classes</b>.name
+ *
+ * @param offset
+ * is the current offset
+ * @return the specific offset, the given offset is returned by default
+ */
+ private int getSpecificOffset(int offset) {
+ CSTNode cstNode = getCSTNode(offset, offset);
+ int result = offset;
+ if (cstNode != null) {
+ EObject eContainer = cstNode.eContainer();
+ EObject eContainingFeature = cstNode.eContainingFeature();
+ if (cstNode instanceof ModelExpression && eContainer instanceof ForBlock) {
+ if (eContainingFeature == CstPackage.eINSTANCE.getForBlock_IterSet()
+ || eContainingFeature == CstPackage.eINSTANCE.getForBlock_Before()
+ || eContainingFeature == CstPackage.eINSTANCE.getForBlock_Each()
+ || eContainingFeature == CstPackage.eINSTANCE.getForBlock_After()) {
+ result = ((ForBlock)eContainer).getStartPosition();
+ }
+ } else if (cstNode instanceof TemplateOverridesValue && eContainer instanceof Template) {
+ result = ((Template)eContainer).getStartPosition();
+ } else if (cstNode instanceof Variable) {
+ result = cstNode.getStartPosition();
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Loads the "imports" dependencies in the current AST, using the CST information.
+ *
+ * @param vAST
+ * is the current AST model
+ * @param dependenciesURIs
+ * are the URIs of the "imports" dependencies to load
+ */
+ private void loadImportsDependencies(org.eclipse.acceleo.model.mtl.Module vAST, List<URI> dependenciesURIs) {
+ for (Iterator<URI> itDependenciesURIs = dependenciesURIs.iterator(); itDependenciesURIs.hasNext();) {
+ URI oURI = itDependenciesURIs.next();
+ String oName = new Path(oURI.lastSegment()).removeFileExtension().lastSegment();
+ Iterator<ModuleImportsValue> values = getCST().getImports().iterator();
+ while (values.hasNext()) {
+ ModuleImportsValue moduleImportsValue = values.next();
+ if (moduleImportsValue != null && oName.equals(moduleImportsValue.getName())) {
+ org.eclipse.acceleo.model.mtl.Module otherModule = getModule(vAST.eResource().getResourceSet(), oURI);
+ if (otherModule != null && oName.equals(otherModule.getName())
+ && !vAST.getImports().contains(otherModule)) {
+ vAST.getImports().add(otherModule);
+ }
+ break;
+ }
+ }
+
+ }
+ }
+
+ /**
+ * Loads the "extends" dependencies in the current AST, using the CST information.
+ *
+ * @param vAST
+ * is the current AST model
+ * @param dependenciesURIs
+ * are the URIs of the "extends" dependencies to load
+ */
+ private void loadExtendsDependencies(org.eclipse.acceleo.model.mtl.Module vAST, List<URI> dependenciesURIs) {
+ for (Iterator<URI> itDependenciesURIs = dependenciesURIs.iterator(); itDependenciesURIs.hasNext();) {
+ URI oURI = itDependenciesURIs.next();
+ String oName = new Path(oURI.lastSegment()).removeFileExtension().lastSegment();
+ Iterator<ModuleExtendsValue> values = getCST().getExtends().iterator();
+ while (values.hasNext()) {
+ ModuleExtendsValue moduleExtendsValue = values.next();
+ if (moduleExtendsValue != null && oName.equals(moduleExtendsValue.getName())) {
+ org.eclipse.acceleo.model.mtl.Module otherModule = getModule(vAST.eResource().getResourceSet(), oURI);
+ if (otherModule != null && oName.equals(otherModule.getName())
+ && !vAST.getExtends().contains(otherModule)) {
+ vAST.getExtends().add(otherModule);
+ }
+ break;
+ }
+ }
+
+ }
+ }
+
+ /**
+ * Returns the first root element of the resource resolved by the URI. The first root element must be of
+ * type 'Module'.
+ *
+ * @param resourceSet
+ * is the resource set
+ * @param uri
+ * the URI to resolve.
+ * @return the first root element of the resource resolved by the URI, or null if there isn't one.
+ */
+ private org.eclipse.acceleo.model.mtl.Module getModule(ResourceSet resourceSet, URI uri) {
+ try {
+ EObject root = ModelUtils.load(uri, resourceSet);
+ if (root instanceof org.eclipse.acceleo.model.mtl.Module) {
+ return (org.eclipse.acceleo.model.mtl.Module)root;
+ }
+ } catch (IOException e) {
+ AcceleoUIActivator.getDefault().getLog().log(
+ new Status(IStatus.ERROR, AcceleoUIActivator.PLUGIN_ID, e.getMessage(), e));
+ }
+ return null;
+ }
+
+ /**
+ * Gets the meta-model types.
+ *
+ * @return the meta-model objects, or an empty list
+ */
+ public List<EClassifier> getTypes() {
+ if (getCST() != null) {
+ org.eclipse.acceleo.model.mtl.Module vAST = source.getAST();
+ OCLParser oclParser;
+ if (vAST == null) {
+ createAST();
+ vAST = source.getAST();
+ }
+ if (vAST != null) {
+ URI uri = vAST.eResource().getURI();
+ vAST = (org.eclipse.acceleo.model.mtl.Module)EcoreUtil.copy(vAST);
+ ResourceSet resourceSet = new ResourceSetImpl();
+ Resource resource = ModelUtils.createResource(uri, resourceSet);
+ resource.getContents().add(vAST);
+ oclParser = new OCLParser(resource);
+ List<URI> dependenciesURIs = getAccessibleOutputFiles();
+ loadImportsDependencies(vAST, dependenciesURIs);
+ loadExtendsDependencies(vAST, dependenciesURIs);
+ oclParser.addRecursivelyMetamodelsToScope(vAST);
+ List<EClassifier> result = oclParser.getTypes();
+ Iterator<Resource> resources = resourceSet.getResources().iterator();
+ while (resources.hasNext()) {
+ resources.next().unload();
+ }
+ return result;
+ }
+ }
+ return new ArrayList<EClassifier>();
+ }
+
+ /**
+ * Gets all the accessible output files (EMTL) of this project. It means the files of the project and the
+ * files of the required plugins.
+ *
+ * @return the URIs of the output files, there are 'plugin' URIs and 'workspace' URIs...
+ */
+ public List<URI> getAccessibleOutputFiles() {
+ if (acceleoProject != null) {
+ return acceleoProject.getAccessibleOutputFiles();
+ } else {
+ return new ArrayList<URI>();
+ }
+ }
+
+ /**
+ * Returns the text of the source.
+ *
+ * @return the text of the source
+ */
+ public String getText() {
+ return source.getBuffer().toString();
+ }
+
+ /**
+ * Creates an AST model. You can get it with the method <code>getAST</code>. The resolution step isn't
+ * executed.
+ */
+ protected void createAST() {
+ URI fileURI;
+ if (file != null) {
+ IPath outputPath = acceleoProject.getOutputFilePath(file);
+ if (outputPath != null) {
+ fileURI = URI.createPlatformResourceURI(outputPath.toString(), false);
+ } else {
+ fileURI = URI.createPlatformResourceURI(file.getFullPath().removeFileExtension()
+ .addFileExtension(IAcceleoConstants.EMTL_FILE_EXTENSION).toString(), false);
+ }
+ } else {
+ fileURI = URI.createURI(DEFAULT_EMTL_URI);
+ }
+ ResourceSet oResourceSet = new ResourceSetImpl();
+ Resource oResource = ModelUtils.createResource(fileURI, oResourceSet);
+ List<URI> resourceSetURIs = new ArrayList<URI>();
+ resourceSetURIs.add(fileURI);
+ // We don't have to create the CST : source.createCST();
+ source.createAST(oResource);
+ }
+
+ /**
+ * Gets the nearest AST node at the given position.
+ *
+ * @param posBegin
+ * is the beginning index
+ * @param posEnd
+ * is the ending index
+ * @return the nearest AST node
+ */
+ public ASTNode getASTNode(int posBegin, int posEnd) {
+ if (posBegin > -1) {
+ org.eclipse.acceleo.model.mtl.Module vAST = getAST();
+ if (vAST != null) {
+ List<URI> dependenciesURIs = getAccessibleOutputFiles();
+ loadImportsDependencies(vAST, dependenciesURIs);
+ loadExtendsDependencies(vAST, dependenciesURIs);
+ source.resolveAST(posBegin, posEnd);
+ ASTNode candidate = null;
+ ASTNode childrenCandidate = getChildrenCandidate(vAST, posBegin, posEnd);
+ while (childrenCandidate != null) {
+ candidate = childrenCandidate;
+ childrenCandidate = getChildrenCandidate(candidate, posBegin, posEnd);
+ }
+ return candidate;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Gets the nearest AST child at the given position. It browses the children of the given candidate and
+ * returns the nearest children if it exists.
+ *
+ * @param candidate
+ * is the current candidate to browse
+ * @param posBegin
+ * is the beginning index
+ * @param posEnd
+ * is the ending index
+ * @return the nearest AST node in the children of the current candidate
+ */
+ private ASTNode getChildrenCandidate(EObject candidate, int posBegin, int posEnd) {
+ Iterator<EObject> itContents = candidate.eContents().iterator();
+ while (itContents.hasNext()) {
+ EObject eContent = itContents.next();
+ if (eContent instanceof ASTNode) {
+ ASTNode astNode = (ASTNode)eContent;
+ int startPosition = astNode.getStartPosition();
+ int endPosition = astNode.getEndPosition();
+ assert startPosition > -1 && endPosition > -1;
+ if (startPosition <= posBegin && endPosition >= posEnd) {
+ return astNode;
+ }
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoTemplateReconcilingStrategy.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoTemplateReconcilingStrategy.java
new file mode 100644
index 0000000..da68a8d
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/AcceleoTemplateReconcilingStrategy.java
@@ -0,0 +1,323 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.editors.template;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.reconciler.DirtyRegion;
+import org.eclipse.jface.text.reconciler.IReconcilingStrategy;
+import org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.projection.ProjectionAnnotation;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * This reconciling strategy will allow us to enable folding support in the Acceleo Template editor.
+ * <p>
+ * Folding rules are as follows :
+ * <ol>
+ * <li>All items stated below as &quot;foldable&quot; will effectively be if they span more than 2 lines.</li>
+ * <li>Comments located before the module statement are considered foldable.</li>
+ * <li>The module block itself is foldable.</li>
+ * <li>Templates, Macros and Queries are foldable.</li>
+ * <li>Within a module, comments located outside of Templates, Macros and Queries are foldable.</li>
+ * </ol>
+ * </p>
+ *
+ * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
+ */
+public final class AcceleoTemplateReconcilingStrategy implements IReconcilingStrategy, IReconcilingStrategyExtension {
+ /** This will be matched against to determine if we are on a comment statement. */
+ private static final String COMMENT_STATEMENT_NAME = "comment"; //$NON-NLS-1$
+
+ /** This will be matched against to determine if we are on a macro statement. */
+ private static final String MACRO_STATEMENT_NAME = "macro"; //$NON-NLS-1$
+
+ /** This will be matched against to determine if we are on a query statement. */
+ private static final String QUERY_STATEMENT_NAME = "query"; //$NON-NLS-1$
+
+ /** This will be matched against to determine if we are on a template statement. */
+ private static final String TEMPLATE_STATEMENT_NAME = "template"; //$NON-NLS-1$
+
+ /**
+ * This will hold the list of all annotations that have been added since the last reconciling.
+ */
+ protected final Map<Annotation, Position> addedAnnotations = new HashMap<Annotation, Position>();
+
+ /** Current known positions of foldable block. */
+ protected final Map<Annotation, Position> currentAnnotations = new HashMap<Annotation, Position>();
+
+ /**
+ * This will hold the list of all annotations that have been removed since the last reconciling.
+ */
+ protected final List<Annotation> deletedAnnotations = new ArrayList<Annotation>();
+
+ /** Editor this provides folding support to. */
+ protected final AcceleoEditor editor;
+
+ /**
+ * This will hold the list of all annotations that have been modified since the last reconciling.
+ */
+ protected final Map<Annotation, Position> modifiedAnnotations = new HashMap<Annotation, Position>();
+
+ /** The document we'll seek foldable blocks in. */
+ private IDocument document;
+
+ /** Current offset. */
+ private int offset;
+
+ /** The statement start delimiter ('[' at current). */
+ private char statementStart = '[';
+
+ /**
+ * Instantiates the reconciling strategy for a given editor.
+ *
+ * @param editor
+ * Editor which we seek to provide folding support for.
+ */
+ public AcceleoTemplateReconcilingStrategy(AcceleoEditor editor) {
+ this.editor = editor;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension#initialReconcile()
+ */
+ public void initialReconcile() {
+ offset = 0;
+ computePositions();
+ updateFoldingStructure();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.jface.text.reconciler.IReconcilingStrategy#reconcile(org.eclipse.jface.text.reconciler.DirtyRegion,
+ * org.eclipse.jface.text.IRegion)
+ */
+ public void reconcile(DirtyRegion dirtyRegion, IRegion subRegion) {
+ reconcile(subRegion);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.jface.text.reconciler.IReconcilingStrategy#reconcile(org.eclipse.jface.text.IRegion)
+ */
+ public void reconcile(IRegion partition) {
+ offset = partition.getOffset();
+ computePositions();
+ updateFoldingStructure();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.jface.text.reconciler.IReconcilingStrategy#setDocument(org.eclipse.jface.text.IDocument)
+ */
+ public void setDocument(IDocument document) {
+ this.document = document;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension#setProgressMonitor(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ public void setProgressMonitor(IProgressMonitor monitor) {
+ // none
+ }
+
+ /**
+ * This will compute the current block positions. The offset at which computations start is determined by
+ * {@link #offset}.
+ */
+ private void computePositions() {
+ deletedAnnotations.clear();
+ modifiedAnnotations.clear();
+ addedAnnotations.clear();
+ deletedAnnotations.addAll(currentAnnotations.keySet());
+ for (Map.Entry<Annotation, Position> entry : currentAnnotations.entrySet()) {
+ final Position position = entry.getValue();
+ if (position.getOffset() + position.getLength() < offset) {
+ deletedAnnotations.remove(entry.getKey());
+ }
+ }
+ try {
+ boolean eof = seekStatementStart();
+ int startOffset = offset;
+ while (!eof) {
+ // set offset after the block start delimiter.
+ offset += 1;
+
+ // See computations rules in this class' javadoc
+ if (COMMENT_STATEMENT_NAME.equals(document.get(offset, COMMENT_STATEMENT_NAME.length()))) {
+ eof = seekCommentEnd();
+ final int endOffset = offset++;
+ if (document.getNumberOfLines(startOffset, endOffset - startOffset) > 2) {
+ createOrUpdateAnnotation(startOffset, endOffset - startOffset, false);
+ }
+ } else {
+ String moduleElement = null;
+ if (MACRO_STATEMENT_NAME.equals(document.get(offset, MACRO_STATEMENT_NAME.length()))) {
+ moduleElement = MACRO_STATEMENT_NAME;
+ } else if (TEMPLATE_STATEMENT_NAME.equals(document.get(offset, TEMPLATE_STATEMENT_NAME
+ .length()))) {
+ moduleElement = TEMPLATE_STATEMENT_NAME;
+ } else if (QUERY_STATEMENT_NAME.equals(document
+ .get(offset, QUERY_STATEMENT_NAME.length()))) {
+ moduleElement = QUERY_STATEMENT_NAME;
+ }
+ if (moduleElement != null) {
+ eof = seekModuleElementEnd(moduleElement);
+ if (document.getNumberOfLines(startOffset, offset - startOffset) > 2) {
+ createOrUpdateAnnotation(startOffset, offset - startOffset, false);
+ }
+ }
+ }
+
+ eof = seekStatementStart();
+ startOffset = offset;
+ }
+ } catch (BadLocationException e) {
+ // Nothing to do
+ }
+ for (Annotation deleted : deletedAnnotations) {
+ currentAnnotations.remove(deleted);
+ }
+ }
+
+ /**
+ * This will update lists {@link #deletedAnnotations}, {@link #addedAnnotations} and
+ * {@link #modifiedAnnotations} according to the given values.
+ *
+ * @param newOffset
+ * Offset of the text we want the annotation updated of.
+ * @param newLength
+ * Length of the text we want the annotation updated of.
+ * @param initiallyCollapsed
+ * Indicates that the created annotation should be folded from start.
+ * @throws BadLocationException
+ * Thrown if we try and get an out of range character. Should not happen.
+ */
+ private void createOrUpdateAnnotation(int newOffset, int newLength, boolean initiallyCollapsed)
+ throws BadLocationException {
+ boolean createAnnotation = true;
+ final Map<Annotation, Position> copy = new HashMap<Annotation, Position>(currentAnnotations);
+ final String text = document.get(newOffset, newLength);
+ for (Map.Entry<Annotation, Position> entry : copy.entrySet()) {
+ if (entry.getKey().getText().equals(text)) {
+ createAnnotation = false;
+ final Position oldPosition = entry.getValue();
+ if (oldPosition.getOffset() != newOffset || oldPosition.getLength() != newLength) {
+ final Position newPosition = new Position(newOffset, newLength);
+ modifiedAnnotations.put(entry.getKey(), newPosition);
+ currentAnnotations.put(entry.getKey(), newPosition);
+ }
+ deletedAnnotations.remove(entry.getKey());
+ break;
+ }
+ }
+ if (createAnnotation) {
+ final Annotation annotation = new ProjectionAnnotation(initiallyCollapsed);
+ annotation.setText(text);
+ final Position position = new Position(newOffset, newLength);
+ currentAnnotations.put(annotation, position);
+ addedAnnotations.put(annotation, position);
+ }
+ }
+
+ /**
+ * Eats all chars away till we find the "<code>[/comment</code>" String.
+ *
+ * @return <code>true</code> if the end of file has been reached. <code>false</code> otherwise.
+ * @throws BadLocationException
+ * Thrown if we try and get an out of range character. Should not happen.
+ */
+ private boolean seekCommentEnd() throws BadLocationException {
+ char next = document.getChar(offset);
+ boolean eof = offset + 1 >= document.getLength();
+ while (!eof && next != statementStart) {
+ offset++;
+ next = document.getChar(offset);
+ }
+ // char is the sought delimiter
+ if (!eof && '/' != document.getChar(offset + 1)
+ && COMMENT_STATEMENT_NAME != document.get(offset + 2, COMMENT_STATEMENT_NAME.length())) {
+ offset++;
+ seekCommentEnd();
+ }
+ return eof;
+ }
+
+ /**
+ * Eats characters away until we find the end of a module element.
+ *
+ * @param moduleElement
+ * Name of the module element we seek the end of.
+ * @return <code>true</code> if the end of file has been reached. <code>false</code> otherwise.
+ * @throws BadLocationException
+ * Thrown if we try and get an out of range character. Should not happen.
+ */
+ private boolean seekModuleElementEnd(String moduleElement) throws BadLocationException {
+ boolean eof = offset + moduleElement.length() + 2 >= document.getLength();
+ char next = document.getChar(offset);
+ while (!eof && next != statementStart) {
+ eof = offset + moduleElement.length() + 2 >= document.getLength();
+ next = document.getChar(offset++);
+ }
+ if ('/' != document.getChar(offset)
+ || !moduleElement.equals(document.get(offset + 1, moduleElement.length()))) {
+ offset++;
+ seekModuleElementEnd(moduleElement);
+ }
+ eof = offset + moduleElement.length() + 2 >= document.getLength();
+ return eof;
+ }
+
+ /**
+ * Eats chars away till we find a {@link #statementStart} char.
+ *
+ * @return <code>true</code> if the end of file has been reached. <code>false</code> otherwise.
+ * @throws BadLocationException
+ * Thrown if we try and get an out of range character. Should not happen.
+ */
+ private boolean seekStatementStart() throws BadLocationException {
+ char next = document.getChar(offset);
+ boolean eof = offset + 1 >= document.getLength();
+ while (!eof && next != statementStart) {
+ offset++;
+ next = document.getChar(offset);
+ eof = offset + 1 == document.getLength();
+ }
+ return eof;
+ }
+
+ /**
+ * Updates the editor's folding structure.
+ */
+ private void updateFoldingStructure() {
+ Display.getDefault().asyncExec(new Runnable() {
+ public void run() {
+ editor.updateFoldingStructure(addedAnnotations, deletedAnnotations, modifiedAnnotations);
+ }
+ });
+ }
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/ColorManager.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/ColorManager.java
new file mode 100644
index 0000000..d8fed8e
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/ColorManager.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.editors.template;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * The color manager for the template editor. It is often used for syntax highlighting.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class ColorManager {
+
+ /**
+ * Created colors.
+ */
+ protected Map<RGB, Color> fColorTable = new HashMap<RGB, Color>(10);
+
+ /**
+ * It disposes color manager.
+ */
+ public void dispose() {
+ Iterator<Color> e = fColorTable.values().iterator();
+ while (e.hasNext()) {
+ e.next().dispose();
+ }
+ }
+
+ /**
+ * Gets the color for the given description (Red, Green, Blue).
+ *
+ * @param rgb
+ * is the description of color
+ * @return the color
+ */
+ public Color getColor(RGB rgb) {
+ Color color = fColorTable.get(rgb);
+ if (color == null) {
+ color = new Color(Display.getCurrent(), rgb);
+ fColorTable.put(rgb, color);
+ }
+ return color;
+ }
+
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/actions/CommentAction.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/actions/CommentAction.java
new file mode 100644
index 0000000..ceb8fbb
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/actions/CommentAction.java
@@ -0,0 +1,135 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.editors.template.actions;
+
+import org.eclipse.acceleo.internal.ide.ui.editors.template.AcceleoEditor;
+import org.eclipse.acceleo.parser.cst.CSTNode;
+import org.eclipse.acceleo.parser.cst.Comment;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IObjectActionDelegate;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * An action to comment a line.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class CommentAction extends Action implements IWorkbenchWindowActionDelegate, IObjectActionDelegate {
+
+ /**
+ * The action ID.
+ */
+ public static final String ACTION_ID = "org.eclipse.acceleo.ide.ui.editors.template.actions.CommentAction"; //$NON-NLS-1$
+
+ /**
+ * The associated command ID.
+ */
+ public static final String COMMAND_ID = "org.eclipse.acceleo.ide.ui.comment"; //$NON-NLS-1$
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction)
+ */
+ public void run(IAction action) {
+ super.run();
+ AcceleoEditor editor = null;
+ IDocument document = null;
+ ITextSelection selection = null;
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (window != null && window.getActivePage() != null
+ && window.getActivePage().getActiveEditor() instanceof AcceleoEditor) {
+ editor = (AcceleoEditor)window.getActivePage().getActiveEditor();
+ document = editor.getDocumentProvider().getDocument(editor.getEditorInput());
+ if (editor.getSelectionProvider() != null
+ && editor.getSelectionProvider().getSelection() instanceof ITextSelection) {
+ selection = (ITextSelection)editor.getSelectionProvider().getSelection();
+ }
+ }
+ if (editor != null && document != null && selection != null) {
+ int b = selection.getOffset();
+ int e = selection.getOffset() + selection.getLength();
+ String text = document.get();
+ while (b < e && Character.isWhitespace(text.charAt(b))) {
+ b++;
+ }
+ while (e > b && Character.isWhitespace(text.charAt(e - 1))) {
+ e--;
+ }
+ CSTNode cstNode = editor.getContent().getCSTNode(b, e);
+ String newText;
+ if (cstNode instanceof Comment) {
+ b = cstNode.getStartPosition();
+ e = cstNode.getEndPosition();
+ newText = ((Comment)cstNode).getBody();
+ } else {
+ if (b == e) {
+ while (b > 0 && text.charAt(b - 1) != '\n') {
+ b--;
+ }
+ while (e < text.length() && text.charAt(e) != '\r' && text.charAt(e) != '\n') {
+ e++;
+ }
+ }
+ // FIXME comment sections are in IAcceleoConstants ... isn't the following error-prone?
+ newText = "[comment]" + text.substring(b, e) + "[/comment]"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ try {
+ document.replace(b, e - b, newText);
+ } catch (BadLocationException ex) {
+ // continue
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.ui.IWorkbenchWindowActionDelegate#dispose()
+ */
+ public void dispose() {
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.ui.IWorkbenchWindowActionDelegate#init(org.eclipse.ui.IWorkbenchWindow)
+ */
+ public void init(IWorkbenchWindow window) {
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.ui.IActionDelegate#selectionChanged(org.eclipse.jface.action.IAction,
+ * org.eclipse.jface.viewers.ISelection)
+ */
+ public void selectionChanged(IAction action, ISelection selection) {
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.ui.IObjectActionDelegate#setActivePart(org.eclipse.jface.action.IAction,
+ * org.eclipse.ui.IWorkbenchPart)
+ */
+ public void setActivePart(IAction action, IWorkbenchPart targetPart) {
+ }
+
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/actions/OpenDeclarationAction.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/actions/OpenDeclarationAction.java
new file mode 100644
index 0000000..51c08eb
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/actions/OpenDeclarationAction.java
@@ -0,0 +1,149 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.editors.template.actions;
+
+import org.eclipse.acceleo.internal.ide.ui.editors.template.AcceleoEditor;
+import org.eclipse.acceleo.internal.ide.ui.editors.template.utils.OpenDeclarationUtils;
+import org.eclipse.acceleo.parser.cst.CSTNode;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.text.TextSelection;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ocl.utilities.ASTNode;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IObjectActionDelegate;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * An action to open the declaration of the selected element.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class OpenDeclarationAction extends Action implements IWorkbenchWindowActionDelegate, IObjectActionDelegate {
+
+ /**
+ * The action ID.
+ */
+ public static final String ACTION_ID = "org.eclipse.acceleo.ide.ui.editors.template.actions.open.declaration"; //$NON-NLS-1$
+
+ /**
+ * The associated command ID.
+ */
+ public static final String COMMAND_ID = "org.eclipse.acceleo.ide.ui.open.declaration"; //$NON-NLS-1$
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.ui.IWorkbenchWindowActionDelegate#dispose()
+ */
+ public void dispose() {
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.ui.IWorkbenchWindowActionDelegate#init(org.eclipse.ui.IWorkbenchWindow)
+ */
+ public void init(IWorkbenchWindow window) {
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction)
+ */
+ public void run(IAction action) {
+ super.run();
+ IEditorPart part;
+ EObject declaration = null;
+ if (PlatformUI.getWorkbench() != null && PlatformUI.getWorkbench().getActiveWorkbenchWindow() != null
+ && PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage() != null) {
+ part = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor();
+ } else {
+ part = null;
+ }
+ if (part instanceof AcceleoEditor && ((AcceleoEditor)part).getContent() != null) {
+ AcceleoEditor editor = (AcceleoEditor)part;
+ declaration = findDeclaration(editor);
+
+ OpenDeclarationUtils.showEObject(editor.getSite().getPage(), getFileURI(declaration),
+ OpenDeclarationUtils.createRegion(declaration), declaration);
+ }
+ }
+
+ /**
+ * Find the declaration of the text selected in the given editor.
+ *
+ * @param editor
+ * the current opened editor
+ * @return the EObject corresponding to the declaration of the selected element
+ */
+ protected EObject findDeclaration(AcceleoEditor editor) {
+ EObject res = null;
+ int offset;
+ ISelection selection = editor.getSelectionProvider().getSelection();
+ if (selection instanceof TextSelection) {
+ offset = ((TextSelection)selection).getOffset();
+ } else {
+ offset = -1;
+ }
+ ASTNode astNode = editor.getContent().getASTNode(offset, offset);
+ if (astNode != null) {
+ res = OpenDeclarationUtils.findDeclarationFromAST(astNode);
+ }
+ if (res == null) {
+ CSTNode cstNode = editor.getContent().getCSTNode(offset, offset);
+ if (cstNode != null) {
+ res = OpenDeclarationUtils.findDeclarationFromCST(editor, astNode, cstNode);
+ }
+ }
+ return res;
+ }
+
+ /**
+ * Get the file URI for the given EObject.
+ *
+ * @param eObj
+ * the EObject
+ * @return the file URI if any of null
+ */
+ public URI getFileURI(EObject eObj) {
+ URI res = null;
+ if (eObj != null && eObj.eResource() != null) {
+ res = eObj.eResource().getURI();
+ }
+ return res;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.ui.IActionDelegate#selectionChanged(org.eclipse.jface.action.IAction,
+ * org.eclipse.jface.viewers.ISelection)
+ */
+ public void selectionChanged(IAction action, ISelection aSelection) {
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.ui.IObjectActionDelegate#setActivePart(org.eclipse.jface.action.IAction,
+ * org.eclipse.ui.IWorkbenchPart)
+ */
+ public void setActivePart(IAction action, IWorkbenchPart aPart) {
+ }
+
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/actions/references/ReferenceEntry.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/actions/references/ReferenceEntry.java
new file mode 100644
index 0000000..a79a73b
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/actions/references/ReferenceEntry.java
@@ -0,0 +1,168 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.editors.template.actions.references;
+
+import org.eclipse.acceleo.internal.ide.ui.editors.template.AcceleoEditor;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.Region;
+import org.eclipse.ocl.utilities.ASTNode;
+
+/**
+ * This class store the reference position.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class ReferenceEntry implements IAdaptable {
+ /**
+ * The template file.
+ */
+ private IFile templateFile;
+
+ /**
+ * The matching object.
+ */
+ private EObject match;
+
+ /**
+ * A message to display.
+ */
+ private String message;
+
+ /**
+ * The Acceleo editor.
+ */
+ private AcceleoEditor editor;
+
+ /**
+ * Constructor.
+ *
+ * @param templateFile
+ * the template file
+ * @param match
+ * the matching object
+ * @param editor
+ * the Acceleo editor
+ */
+ public ReferenceEntry(IFile templateFile, EObject match, AcceleoEditor editor) {
+ this(templateFile, match, editor, ""); //$NON-NLS-1$
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param templateFile
+ * the template file
+ * @param match
+ * the region
+ * @param editor
+ * the Acceleo editor
+ * @param message
+ * the message
+ */
+ public ReferenceEntry(IFile templateFile, EObject match, AcceleoEditor editor, String message) {
+ this.templateFile = templateFile;
+ this.match = match;
+ this.message = message;
+ this.editor = editor;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
+ */
+ @SuppressWarnings("unchecked")
+ public Object getAdapter(Class adapter) {
+ if (IResource.class.equals(adapter)) {
+ return templateFile;
+ }
+ return null;
+ }
+
+ /**
+ * Getter for the template file.
+ *
+ * @return the template file
+ */
+ public IFile getTemplateFile() {
+ return templateFile;
+ }
+
+ /**
+ * Getter for the matching object.
+ *
+ * @return the matching object
+ */
+ public EObject getMatch() {
+ return match;
+ }
+
+ /**
+ * Getter for the message.
+ *
+ * @return the message
+ */
+ public String getMessage() {
+ return message;
+ }
+
+ /**
+ * Getter for the Acceleo editor.
+ *
+ * @return the Acceleo editor
+ */
+ public AcceleoEditor getEditor() {
+ return editor;
+ }
+
+ /**
+ * Creates a region for the current match.
+ *
+ * @return the region of the current match
+ */
+ public IRegion getRegion() {
+ if (match instanceof ASTNode) {
+ return createRegion((ASTNode)match);
+ } else {
+ return new Region(0, 0);
+ }
+ }
+
+ /**
+ * Creates a region for the given module element.
+ *
+ * @param eModuleElement
+ * is the module element
+ * @return a region in the text
+ */
+ private IRegion createRegion(ASTNode eModuleElement) {
+ int b = eModuleElement.getStartPosition();
+ if (b > -1) {
+ int e = eModuleElement.getEndPosition();
+ return new Region(b, e - b);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ return templateFile.getName() + ": " + message; //$NON-NLS-1$
+ }
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/actions/references/ReferenceLabelProvider.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/actions/references/ReferenceLabelProvider.java
new file mode 100644
index 0000000..05569ab
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/actions/references/ReferenceLabelProvider.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.editors.template.actions.references;
+
+import org.eclipse.acceleo.ide.ui.AcceleoUIActivator;
+import org.eclipse.acceleo.model.mtl.Module;
+import org.eclipse.acceleo.model.mtl.ModuleElement;
+import org.eclipse.acceleo.model.mtl.TypedModel;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.ocl.ecore.Variable;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.ui.model.WorkbenchLabelProvider;
+
+/**
+ * This class provide labels for the references search.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class ReferenceLabelProvider extends LabelProvider {
+
+ /**
+ * The label provider of the workbench.
+ */
+ private WorkbenchLabelProvider labelProvider;
+
+ /**
+ * Constructor.
+ */
+ public ReferenceLabelProvider() {
+ labelProvider = new WorkbenchLabelProvider();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.jface.viewers.LabelProvider#getImage(java.lang.Object)
+ */
+ public Image getImage(Object element) {
+ Image result;
+ if (element instanceof IResource) {
+ result = labelProvider.getImage(element);
+ } else if (element instanceof ReferenceEntry) {
+ ReferenceEntry entry = (ReferenceEntry)element;
+ if (entry.getMatch() instanceof ModuleElement || entry.getMatch() instanceof Variable
+ || entry.getMatch() instanceof Module || entry.getMatch() instanceof TypedModel) {
+ result = AcceleoUIActivator.getDefault().getImage(
+ "/icons/template-editor/" + ((EObject)entry.getMatch()).eClass().getName() + ".gif"); //$NON-NLS-1$ //$NON-NLS-2$
+ } else {
+ result = AcceleoUIActivator.getDefault().getImage("/icons/template-editor/ModelExpression.gif"); //$NON-NLS-1$
+ }
+ } else {
+ result = AcceleoUIActivator.getDefault().getImage("/icons/template-editor/ModelExpression.gif"); //$NON-NLS-1$
+ }
+ return result;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object)
+ */
+ public String getText(Object element) {
+ String res = super.getText(element);
+ if (element instanceof IFile) {
+ res = ((IFile)element).getName();
+ } else if (element instanceof IProject) {
+ res = ((IProject)element).getName();
+ } else if (element instanceof IResource) {
+ res = ((IResource)element).getProjectRelativePath().toString();
+ } else if (element instanceof ReferenceEntry) {
+ res = ((ReferenceEntry)element).getMessage();
+ }
+ return res;
+ }
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/actions/references/ReferenceSorter.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/actions/references/ReferenceSorter.java
new file mode 100644
index 0000000..3c2ac30
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/actions/references/ReferenceSorter.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.editors.template.actions.references;
+
+import org.eclipse.jface.viewers.ViewerSorter;
+
+/**
+ * This class sorts ReferenceEntries.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class ReferenceSorter extends ViewerSorter {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.jface.viewers.ViewerComparator#category(java.lang.Object)
+ */
+ public int category(Object element) {
+ if (element instanceof ReferenceEntry) {
+ return 0;
+ } else {
+ return 1;
+ }
+ }
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/actions/references/ReferencesSearchAction.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/actions/references/ReferencesSearchAction.java
new file mode 100644
index 0000000..54a7f65
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/actions/references/ReferencesSearchAction.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.editors.template.actions.references;
+
+import org.eclipse.acceleo.internal.ide.ui.editors.template.AcceleoEditor;
+import org.eclipse.acceleo.internal.ide.ui.editors.template.actions.OpenDeclarationAction;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.text.TextSelection;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.search.ui.ISearchQuery;
+import org.eclipse.search.ui.NewSearchUI;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * This action trigger the references search.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class ReferencesSearchAction extends OpenDeclarationAction {
+
+ /**
+ * The action ID.
+ */
+ public static final String ACTION_ID = "org.eclipse.acceleo.ide.ui.editors.template.actions.search.references"; //$NON-NLS-1$
+
+ /**
+ * The associated command ID.
+ */
+ public static final String COMMAND_ID = "org.eclipse.acceleo.ide.ui.search.references"; //$NON-NLS-1$
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction)
+ */
+ @Override
+ public void run(IAction action) {
+ super.run();
+ IEditorPart part;
+ EObject declaration = null;
+ if (PlatformUI.getWorkbench() != null && PlatformUI.getWorkbench().getActiveWorkbenchWindow() != null
+ && PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage() != null) {
+ part = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor();
+ } else {
+ part = null;
+ }
+ if (part instanceof AcceleoEditor && ((AcceleoEditor)part).getContent() != null) {
+ AcceleoEditor editor = (AcceleoEditor)part;
+ declaration = findDeclaration(editor);
+ if (declaration == null) {
+ int offset;
+ ISelection selection = editor.getSelectionProvider().getSelection();
+ if (selection instanceof TextSelection) {
+ offset = ((TextSelection)selection).getOffset();
+ declaration = editor.getContent().getASTNode(offset, offset);
+ }
+ }
+ if (declaration != null) {
+ ISearchQuery query = new ReferencesSearchQuery(editor, declaration);
+ NewSearchUI.runQueryInBackground(query);
+ }
+ }
+ }
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/actions/references/ReferencesSearchQuery.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/actions/references/ReferencesSearchQuery.java
new file mode 100644
index 0000000..ac6feee
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/actions/references/ReferencesSearchQuery.java
@@ -0,0 +1,308 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.editors.template.actions.references;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.acceleo.common.IAcceleoConstants;
+import org.eclipse.acceleo.common.utils.ModelUtils;
+import org.eclipse.acceleo.ide.ui.AcceleoUIActivator;
+import org.eclipse.acceleo.ide.ui.natures.AcceleoNature;
+import org.eclipse.acceleo.ide.ui.resources.AcceleoProject;
+import org.eclipse.acceleo.internal.ide.ui.AcceleoUIMessages;
+import org.eclipse.acceleo.internal.ide.ui.editors.template.AcceleoEditor;
+import org.eclipse.acceleo.internal.parser.cst.utils.FileContent;
+import org.eclipse.acceleo.model.mtl.Module;
+import org.eclipse.acceleo.model.mtl.ModuleElement;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.Region;
+import org.eclipse.ocl.utilities.ASTNode;
+import org.eclipse.search.ui.ISearchQuery;
+import org.eclipse.search.ui.ISearchResult;
+import org.eclipse.search.ui.text.Match;
+
+/**
+ * This class is the query looking for References in Acceleo templates.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class ReferencesSearchQuery implements ISearchQuery {
+ /**
+ * The result where to store matches.
+ */
+ private ReferencesSearchResult searchResult;
+
+ /**
+ * The declaration for which we seek references.
+ */
+ private EObject declaration;
+
+ /**
+ * The Acceleo Editor.
+ */
+ private AcceleoEditor editor;
+
+ /**
+ * Constructor.
+ *
+ * @param editor
+ * the Acceleo editor
+ * @param declaration
+ * the declaration for which we seek references
+ */
+ public ReferencesSearchQuery(AcceleoEditor editor, EObject declaration) {
+ this.declaration = declaration;
+ this.editor = editor;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.search.ui.ISearchQuery#canRerun()
+ */
+ public boolean canRerun() {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.search.ui.ISearchQuery#canRunInBackground()
+ */
+ public boolean canRunInBackground() {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.search.ui.ISearchQuery#getLabel()
+ */
+ public String getLabel() {
+ return AcceleoUIMessages.getString("AcceleoReferencesSearch.Query.Label"); //$NON-NLS-1$
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.search.ui.ISearchQuery#getSearchResult()
+ */
+ public ISearchResult getSearchResult() {
+ if (searchResult == null) {
+ searchResult = new ReferencesSearchResult(this);
+ }
+ return searchResult;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.search.ui.ISearchQuery#run(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ public IStatus run(IProgressMonitor monitor) throws OperationCanceledException {
+ if (declaration != null) {
+ findReferencesForFile();
+ }
+ return Status.OK_STATUS;
+ }
+
+ /**
+ * Compute the references in the workspace of the current declaration.
+ */
+ private void findReferencesForFile() {
+ List<URI> allURIs = new ArrayList<URI>();
+ URI newResourceURI = URI.createPlatformResourceURI(new AcceleoProject(editor.getContent().getFile()
+ .getProject()).getOutputFilePath(editor.getContent().getFile()).toString(), false);
+ allURIs.add(newResourceURI);
+ IProject project = editor.getFile().getProject();
+ for (URI uri : new AcceleoProject(project).getOutputFiles()) {
+ if (!allURIs.contains(uri)) {
+ allURIs.add(uri);
+ }
+ }
+ IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
+ for (int i = 0; i < projects.length; i++) {
+ try {
+ if (projects[i] != project && projects[i].isAccessible()
+ && projects[i].hasNature(AcceleoNature.NATURE_ID)) {
+ AcceleoProject acceleoProject = new AcceleoProject(projects[i]);
+ for (URI uri : acceleoProject.getOutputFiles()) {
+ if (!allURIs.contains(uri)) {
+ allURIs.add(uri);
+ }
+ }
+ }
+ } catch (CoreException e) {
+ AcceleoUIActivator.getDefault().getLog().log(e.getStatus());
+ }
+ }
+ ResourceSet newResourceSet = new ResourceSetImpl();
+ for (URI uri : allURIs) {
+ try {
+ ModelUtils.load(uri, newResourceSet);
+ } catch (IOException e) {
+ // do nothing
+ }
+ }
+ EcoreUtil.resolveAll(newResourceSet);
+ for (Resource resource : newResourceSet.getResources()) {
+ if (resource.getContents().size() > 0 && resource.getContents().get(0) instanceof Module) {
+ scanModuleForDeclaration((Module)resource.getContents().get(0));
+ }
+ }
+ for (Resource resource : newResourceSet.getResources()) {
+ resource.unload();
+ }
+ }
+
+ /**
+ * Seek references to the declaration in the given module.
+ *
+ * @param module
+ * the module
+ */
+ private void scanModuleForDeclaration(Module module) {
+ IPath emtlPath = new Path(module.eResource().getURI().toPlatformString(true));
+ if (emtlPath.segmentCount() > 1 && ResourcesPlugin.getWorkspace().getRoot().exists(emtlPath)) {
+ IFile emtlFile = ResourcesPlugin.getWorkspace().getRoot().getFile(emtlPath);
+ IPath mtlPath = new AcceleoProject(emtlFile.getProject()).getInputFilePath(emtlPath);
+ IFile mtlFile = ResourcesPlugin.getWorkspace().getRoot().getFile(mtlPath);
+ if (mtlFile.exists()) {
+ StringBuffer acceleoText = FileContent.getFileContent(mtlFile.getLocation().toFile());
+ scanModuleForDeclaration(mtlFile, acceleoText, module);
+ }
+ }
+ }
+
+ /**
+ * Seek references to the declaration in the given Acceleo file, starting by the root element of the AST
+ * model.
+ *
+ * @param mtlFile
+ * is the file
+ * @param acceleoText
+ * is the current modified text of the Acceleo file
+ * @param module
+ * is the root element of the AST model
+ */
+ private void scanModuleForDeclaration(IFile mtlFile, StringBuffer acceleoText, Module module) {
+ addASTNode(mtlFile, acceleoText, module);
+ Iterator<EObject> it = module.eAllContents();
+ while (it.hasNext()) {
+ addASTNode(mtlFile, acceleoText, it.next());
+ }
+ }
+
+ /**
+ * Try to seek references to the declaration in the given Acceleo file, at the given AST node.
+ *
+ * @param mtlFile
+ * is the file
+ * @param acceleoText
+ * is the current modified text of the Acceleo file
+ * @param astNode
+ * is the current AST node
+ */
+ private void addASTNode(IFile mtlFile, StringBuffer acceleoText, EObject astNode) {
+ boolean isRef = isMatching(astNode, declaration);
+ if (!isRef) {
+ for (EObject eObj : astNode.eCrossReferences()) {
+ if (isMatching(eObj, declaration)) {
+ isRef = true;
+ break;
+ }
+ }
+ }
+ if (isRef) {
+ IRegion region;
+ if (astNode instanceof ASTNode) {
+ region = createRegion((ASTNode)astNode);
+ } else {
+ region = new Region(0, 0);
+ }
+ String message;
+ if (region.getOffset() > -1 && region.getOffset() + region.getLength() <= acceleoText.length()) {
+ message = acceleoText.substring(region.getOffset(), region.getOffset() + region.getLength());
+ if (message.startsWith(IAcceleoConstants.DEFAULT_BEGIN)
+ && message.indexOf(IAcceleoConstants.DEFAULT_END) > -1) {
+ message = message.substring(0, message.indexOf(IAcceleoConstants.DEFAULT_END) + 1);
+ }
+ } else {
+ message = ""; //$NON-NLS-1$
+ }
+ searchResult.addMatch(new Match(new ReferenceEntry(mtlFile, astNode, editor, message), region
+ .getOffset(), region.getLength()));
+ }
+ }
+
+ /**
+ * Indicates if the given AST objects are matching.
+ *
+ * @param o1
+ * is the first object
+ * @param o2
+ * is the second object
+ * @return true if the element names are the same
+ */
+ private boolean isMatching(EObject o1, EObject o2) {
+ boolean result;
+ if (o1.eClass().getName().equals(o2.eClass().getName())) {
+ if (o1 instanceof ModuleElement && o2 instanceof ModuleElement) {
+ result = ((ModuleElement)o1).getName().equals(((ModuleElement)o2).getName());
+ } else if (o1 instanceof org.eclipse.ocl.ecore.Variable
+ && o2 instanceof org.eclipse.ocl.ecore.Variable) {
+ result = ((org.eclipse.ocl.ecore.Variable)o1).getName().equals(
+ ((org.eclipse.ocl.ecore.Variable)o2).getName());
+ } else {
+ result = EcoreUtil.equals(o1, o2);
+ }
+ } else {
+ result = EcoreUtil.equals(o1, o2);
+ }
+ return result;
+ }
+
+ /**
+ * Creates a region for the given module element.
+ *
+ * @param astNode
+ * is the module element
+ * @return a region in the text
+ */
+ private IRegion createRegion(ASTNode astNode) {
+ int b = astNode.getStartPosition();
+ if (b > -1) {
+ int e = astNode.getEndPosition();
+ return new Region(b, e - b);
+ } else {
+ return null;
+ }
+ }
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/actions/references/ReferencesSearchResult.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/actions/references/ReferencesSearchResult.java
new file mode 100644
index 0000000..441c9c1
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/actions/references/ReferencesSearchResult.java
@@ -0,0 +1,152 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.editors.template.actions.references;
+
+import org.eclipse.acceleo.internal.ide.ui.AcceleoUIMessages;
+import org.eclipse.acceleo.internal.ide.ui.editors.template.AcceleoEditor;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.search.ui.ISearchQuery;
+import org.eclipse.search.ui.text.AbstractTextSearchResult;
+import org.eclipse.search.ui.text.IEditorMatchAdapter;
+import org.eclipse.search.ui.text.IFileMatchAdapter;
+import org.eclipse.search.ui.text.Match;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IFileEditorInput;
+
+/**
+ * This class store results of the query. It is also an adapter.
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class ReferencesSearchResult extends AbstractTextSearchResult implements IEditorMatchAdapter, IFileMatchAdapter {
+ /**
+ * The query.
+ */
+ private ReferencesSearchQuery query;
+
+ /**
+ * Constructor.
+ *
+ * @param query
+ * the query to use
+ */
+ public ReferencesSearchResult(ReferencesSearchQuery query) {
+ this.query = query;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.search.ui.text.AbstractTextSearchResult#getEditorMatchAdapter()
+ */
+ public IEditorMatchAdapter getEditorMatchAdapter() {
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.search.ui.text.AbstractTextSearchResult#getFileMatchAdapter()
+ */
+ public IFileMatchAdapter getFileMatchAdapter() {
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.search.ui.ISearchResult#getImageDescriptor()
+ */
+ public ImageDescriptor getImageDescriptor() {
+ return ImageDescriptor.getMissingImageDescriptor();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.search.ui.ISearchResult#getLabel()
+ */
+ public String getLabel() {
+ return AcceleoUIMessages.getString("AcceleoReferencesSearch.Result.Label"); //$NON-NLS-1$
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.search.ui.ISearchResult#getQuery()
+ */
+ public ISearchQuery getQuery() {
+ return query;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.search.ui.ISearchResult#getTooltip()
+ */
+ public String getTooltip() {
+ return AcceleoUIMessages.getString("AcceleoReferencesSearch.Result.Tooltip"); //$NON-NLS-1$
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.search.ui.text.IEditorMatchAdapter#computeContainedMatches(org.eclipse.search.ui.text.AbstractTextSearchResult,
+ * org.eclipse.ui.IEditorPart)
+ */
+ public Match[] computeContainedMatches(AbstractTextSearchResult result, IEditorPart editor) {
+ IFile file = null;
+ if (editor.getEditorInput() instanceof IFileEditorInput) {
+ file = ((IFileEditorInput)editor.getEditorInput()).getFile();
+ }
+ return result.getMatches(file);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.search.ui.text.IEditorMatchAdapter#isShownInEditor(org.eclipse.search.ui.text.Match,
+ * org.eclipse.ui.IEditorPart)
+ */
+ public boolean isShownInEditor(Match match, IEditorPart editor) {
+ if ((editor instanceof AcceleoEditor) && match.getElement() instanceof IFile) {
+ AcceleoEditor acceleoEditor = (AcceleoEditor)editor;
+ IFile matchedFile = (IFile)match.getElement();
+ return acceleoEditor.getFile().equals(matchedFile);
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.search.ui.text.IFileMatchAdapter#computeContainedMatches(org.eclipse.search.ui.text.AbstractTextSearchResult,
+ * org.eclipse.core.resources.IFile)
+ */
+ public Match[] computeContainedMatches(AbstractTextSearchResult result, IFile file) {
+ return result.getMatches(file);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.search.ui.text.IFileMatchAdapter#getFile(java.lang.Object)
+ */
+ public IFile getFile(Object element) {
+ if (element instanceof IFile) {
+ return (IFile)element;
+ } else {
+ return null;
+ }
+ }
+}
diff --git a/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/actions/references/ReferencesSearchViewPage.java b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/actions/references/ReferencesSearchViewPage.java
new file mode 100644
index 0000000..43bceb2
--- /dev/null
+++ b/plugins/org.eclipse.acceleo.ide.ui/src/org/eclipse/acceleo/internal/ide/ui/editors/template/actions/references/ReferencesSearchViewPage.java
@@ -0,0 +1,147 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.internal.ide.ui.editors.template.actions.references;
+
+import org.eclipse.acceleo.ide.ui.resources.AcceleoProject;
+import org.eclipse.acceleo.internal.ide.ui.editors.template.utils.OpenDeclarationUtils;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.search.ui.text.AbstractTextSearchViewPage;
+import org.eclipse.search.ui.text.Match;
+import org.eclipse.ui.IPageLayout;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.part.IShowInTargetList;
+
+/**
+ * This class is the page referenced by the extention point org.eclipse.search.searchResultViewPages. It is
+ * used to show ReferencesSearchResult
+ *
+ * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a>
+ */
+public class ReferencesSearchViewPage extends AbstractTextSearchViewPage implements IAdaptable {
+
+ /**
+ * The show in target constant.
+ */
+ private static final String[] SHOW_IN_TARGETS = new String