Added support for toggling comments with ctrl|cmd+/ in Epsilon editors
diff --git a/plugins/org.eclipse.epsilon.common.dt/plugin.xml b/plugins/org.eclipse.epsilon.common.dt/plugin.xml
index 8be7a30..d76e5f5 100644
--- a/plugins/org.eclipse.epsilon.common.dt/plugin.xml
+++ b/plugins/org.eclipse.epsilon.common.dt/plugin.xml
@@ -77,5 +77,22 @@
                class="org.eclipse.epsilon.common.dt.launching.extensions.ModelTypeExtension"

                defaultName="modelTypeExtension">

          </tool>

+      </extension>

+      <extension

+            point="org.eclipse.ui.bindings">

+         <key

+               commandId="org.eclipse.epsilon.common.dt.editor.AbsractModuleEditor.ToggleComment"

+               contextId="org.eclipse.ui.textEditorScope"

+               schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"

+               sequence="M1+/">

+         </key>

+      </extension>

+      <extension

+            point="org.eclipse.ui.commands">

+         <command

+               categoryId="org.eclipse.ui.category.textEditor"

+               id="org.eclipse.epsilon.common.dt.editor.AbsractModuleEditor.ToggleComment"

+               name="Toggle Comment">

+         </command>

       </extension>
 </plugin>

diff --git a/plugins/org.eclipse.epsilon.common.dt/src/org/eclipse/epsilon/common/dt/editor/AbstractModuleEditor.java b/plugins/org.eclipse.epsilon.common.dt/src/org/eclipse/epsilon/common/dt/editor/AbstractModuleEditor.java
index 92b7fe0..3572f05 100644
--- a/plugins/org.eclipse.epsilon.common.dt/src/org/eclipse/epsilon/common/dt/editor/AbstractModuleEditor.java
+++ b/plugins/org.eclipse.epsilon.common.dt/src/org/eclipse/epsilon/common/dt/editor/AbstractModuleEditor.java
@@ -10,7 +10,15 @@
 package org.eclipse.epsilon.common.dt.editor;

 

 import java.io.File;

-import java.util.*;

+import java.util.ArrayList;

+import java.util.Arrays;

+import java.util.Collection;

+import java.util.HashMap;

+import java.util.HashSet;

+import java.util.List;

+import java.util.Map;

+import java.util.Set;

+

 import org.eclipse.core.resources.IFile;

 import org.eclipse.core.resources.IMarker;

 import org.eclipse.core.resources.IResource;

@@ -67,7 +75,7 @@
 import org.eclipse.ui.texteditor.TextOperationAction;

 

 public abstract class AbstractModuleEditor extends AbstractDecoratedTextEditor {

-	

+

 	protected Color backgroundColor = null;

 	protected Job parseModuleJob = null;

 	protected ArrayList<IModuleParseListener> moduleParsedListeners = new ArrayList<>();

@@ -75,54 +83,53 @@
 	protected EpsilonHighlightingManager highlightingManager;

 

 	public static final String PROBLEM_MARKER = "org.eclipse.epsilon.common.dt.problemmarker";

-	

+

 	private ModuleContentOutlinePage outlinePage;

 

 	public AbstractModuleEditor() {

 		super();

 		setDocumentProvider(new AbstractModuleEditorDocumentProvider());

 		setEditorContextMenuId("#TextEditorContext");

-	    setRulerContextMenuId("editor.rulerMenu");

+		setRulerContextMenuId("editor.rulerMenu");

 		highlightingManager = new EpsilonHighlightingManager();

 		highlightingManager.initialiseDefaultColors();

 	}

-	

+

 	public void addModuleParsedListener(IModuleParseListener listener) {

 		this.moduleParsedListeners.add(listener);

 	}

-	

+

 	public ArrayList<IModuleParseListener> getModuleParsedListeners() {

 		return moduleParsedListeners;

 	}

-	

+

 	public boolean removeModuleParsedListener(IModuleParseListener listener) {

 		return moduleParsedListeners.remove(listener);

 	}

-	

+

 	public void addTemplateContributor(IAbstractModuleEditorTemplateContributor templateContributor) {

 		this.templateContributors.add(templateContributor);

 	}

-	

+

 	public boolean removeTemplateContributor(IAbstractModuleEditorTemplateContributor templateContributor) {

 		return this.templateContributors.remove(templateContributor);

 	}

-	

+

 	protected void notifyModuleParsedListeners(IModule module) {

 		for (IModuleParseListener listener : moduleParsedListeners) {

 			listener.moduleParsed(this, module);

 		}

 	}

-	

+

 	public ModuleElement adaptToAST(Object o) {

 		if (o instanceof ModuleElement) {

 			return (ModuleElement) o;

-		}

-		else return null;

+		} else

+			return null;

 	}

-	

+

 	public void insertText(String text) {

-		IDocument doc = this.getDocumentProvider().getDocument(

-				this.getEditorInput());

+		IDocument doc = this.getDocumentProvider().getDocument(this.getEditorInput());

 		TextSelection selection = (TextSelection) getSelectionProvider().getSelection();

 		try {

 			doc.replace(selection.getOffset(), 0, text);

@@ -130,26 +137,25 @@
 			e.printStackTrace();

 		}

 	}

-	

+

 	public final static String EDITOR_MATCHING_BRACKETS = "matchingBrackets";

-	public final static String EDITOR_MATCHING_BRACKETS_COLOR= "matchingBracketsColor";

-	

+	public final static String EDITOR_MATCHING_BRACKETS_COLOR = "matchingBracketsColor";

+

 	@Override

-	protected void configureSourceViewerDecorationSupport(

-			SourceViewerDecorationSupport support) {

+	protected void configureSourceViewerDecorationSupport(SourceViewerDecorationSupport support) {

 

 		super.configureSourceViewerDecorationSupport(support);

-		char[] matchChars = {'(', ')', '[', ']', '{', '}'}; 		

-		ICharacterPairMatcher matcher = new DefaultCharacterPairMatcher(matchChars ,

+		char[] matchChars = { '(', ')', '[', ']', '{', '}' };

+		ICharacterPairMatcher matcher = new DefaultCharacterPairMatcher(matchChars,

 				IDocumentExtension3.DEFAULT_PARTITIONING);

 		support.setCharacterPairMatcher(matcher);

-		support.setMatchingCharacterPainterPreferenceKeys(EDITOR_MATCHING_BRACKETS,EDITOR_MATCHING_BRACKETS_COLOR);

-		

+		support.setMatchingCharacterPainterPreferenceKeys(EDITOR_MATCHING_BRACKETS, EDITOR_MATCHING_BRACKETS_COLOR);

+

 		IPreferenceStore store = getPreferenceStore();

 		store.setDefault(EDITOR_MATCHING_BRACKETS, true);

 		store.setDefault(EDITOR_MATCHING_BRACKETS_COLOR, "128,128,128");

 	}

-	

+

 	@SuppressWarnings("unchecked")

 	@Override

 	public <T> T getAdapter(Class<T> required) {

@@ -158,48 +164,41 @@
 		}

 		return super.getAdapter(required);

 	}

-	

-	//TODO: (fonso) this list seems incomplete with respect to the book list

+

+	// TODO: (fonso) this list seems incomplete with respect to the book list

 	public List<String> getAssertions() {

 		return Arrays.asList("assert", "assertError");

 	}

-	

+

 	public Collection<String> getTypes() {

 		// The list returned by Arrays.asList cannot be changed in size,

 		// as it is just a wrapper over the Java array. Therefore, any

 		// calls to add/remove will return an UnsupportedOperationException.

-		return new ArrayList<>(Arrays.asList(

-			"String", "Boolean", "Integer", "Real",

-			"Any", "Map", "Collection", "Bag", "Sequence",

-			"Set", "OrderedSet", "Native", "List", "Tuple",

-			"ConcurrentSet", "ConcurrentBag", "ConcurrentMap")

-		);

+		return new ArrayList<>(Arrays.asList("String", "Boolean", "Integer", "Real", "Any", "Map", "Collection", "Bag",

+				"Sequence", "Set", "OrderedSet", "Native", "List", "Tuple", "ConcurrentSet", "ConcurrentBag",

+				"ConcurrentMap"));

 	}

-	

+

 	public abstract List<String> getKeywords();

 

 	public abstract List<String> getBuiltinVariables();

 

 	public ModuleContentOutlinePage createOutlinePage() {

-		

-		ModuleContentOutlinePage outline = 

-			new ModuleContentOutlinePage(

-					this.getDocumentProvider(), 

-					this, 

-					createModuleElementLabelProvider(),

-					createModuleContentProvider());

-				

+

+		ModuleContentOutlinePage outline = new ModuleContentOutlinePage(this.getDocumentProvider(), this,

+				createModuleElementLabelProvider(), createModuleContentProvider());

+

 		addModuleParsedListener(outline);

-		

+

 		return outline;

 	}

-	

+

 	public abstract IModule createModule();

-	

+

 	public abstract ModuleElementLabelProvider createModuleElementLabelProvider();

-	

+

 	protected abstract ModuleContentProvider createModuleContentProvider();

-	

+

 	ProjectionSupport projectionSupport;

 

 	AnnotationModel annotationModel;

@@ -208,33 +207,32 @@
 	public void createPartControl(Composite parent) {

 		super.createPartControl(parent);

 		ProjectionViewer viewer = (ProjectionViewer) getSourceViewer();

-		projectionSupport = new ProjectionSupport(viewer,

-				getAnnotationAccess(), getSharedColors());

+		projectionSupport = new ProjectionSupport(viewer, getAnnotationAccess(), getSharedColors());

 		projectionSupport.install();

 

 		// turn projection mode on

 		viewer.doOperation(ProjectionViewer.TOGGLE);

 		annotationModel = viewer.getProjectionAnnotationModel();

-		//updateFoldingStructure();

+		// updateFoldingStructure();

 	}

 

 	@Override

-	protected ISourceViewer createSourceViewer(Composite parent,

-			IVerticalRuler ruler, int styles) {

+	protected ISourceViewer createSourceViewer(Composite parent, IVerticalRuler ruler, int styles) {

 

-		ISourceViewer viewer = new ProjectionViewer(parent, ruler,

-				getOverviewRuler(), isOverviewRulerVisible(), styles);

-		

-		//IDocument doc = this.getDocumentProvider().getDocument(

-		//		this.getEditorInput());

-		//autoclosingPairManager = new AutoclosingPairManager(doc, getSourceViewerConfiguration().getUndoManager(viewer));

-		//viewer.getTextWidget().addVerifyKeyListener(autoclosingPairManager);

+		ISourceViewer viewer = new ProjectionViewer(parent, ruler, getOverviewRuler(), isOverviewRulerVisible(),

+				styles);

+

+		// IDocument doc = this.getDocumentProvider().getDocument(

+		// this.getEditorInput());

+		// autoclosingPairManager = new AutoclosingPairManager(doc,

+		// getSourceViewerConfiguration().getUndoManager(viewer));

+		// viewer.getTextWidget().addVerifyKeyListener(autoclosingPairManager);

 		getSourceViewerDecorationSupport(viewer);

-		

+

 		return viewer;

 	}

-	

-	//TODO : Improve the folding functionality

+

+	// TODO : Improve the folding functionality

 

 //	boolean useCodeFolding = false;

 //	

@@ -276,33 +274,32 @@
 //		} catch (Exception e) {

 //			e.printStackTrace();

 //		}

-		

-		// annotationModel.modifyAnnotationPosition(annotation,new

-		// Position(0,10));

-		/*

-		 * Annotation[] annotations = new Annotation[positions.size()];

-		 * 

-		 * //this will hold the new annotations along //with their corresponding

-		 * positions HashMap newAnnotations = new HashMap();

-		 * 

-		 * for(int i = 0; i < positions.size();i++) { ProjectionAnnotation

-		 * annotation = new ProjectionAnnotation();

-		 * 

-		 * newAnnotations.put(annotation, positions.get(i));

-		 * 

-		 * annotations[i] = annotation; }

-		 * 

-		 * annotationModel.mmodifyAnnotation(oldAnnotations,

-		 * newAnnotations,null);

-		 * 

-		 * oldAnnotations = annotations;

-		 */

-	//}

-	

+

+	// annotationModel.modifyAnnotationPosition(annotation,new

+	// Position(0,10));

+	/*

+	 * Annotation[] annotations = new Annotation[positions.size()];

+	 * 

+	 * //this will hold the new annotations along //with their corresponding

+	 * positions HashMap newAnnotations = new HashMap();

+	 * 

+	 * for(int i = 0; i < positions.size();i++) { ProjectionAnnotation annotation =

+	 * new ProjectionAnnotation();

+	 * 

+	 * newAnnotations.put(annotation, positions.get(i));

+	 * 

+	 * annotations[i] = annotation; }

+	 * 

+	 * annotationModel.mmodifyAnnotation(oldAnnotations, newAnnotations,null);

+	 * 

+	 * oldAnnotations = annotations;

+	 */

+	// }

+

 	public SourceViewerConfiguration createSourceViewerConfiguration() {

 		return new AbstractModuleEditorSourceViewerConfiguration(this);

 	}

-	

+

 	@Override

 	public void init(IEditorSite site, IEditorInput input) {

 		try {

@@ -310,87 +307,86 @@
 		} catch (PartInitException e) {

 			e.printStackTrace();

 		}

-		

+

 		setSourceViewerConfiguration(createSourceViewerConfiguration());

-		

+

 		PlatformUI.getWorkbench().getThemeManager().addPropertyChangeListener(new ThemeChangeListener() {

 			@Override

 			public void themeChange() {

 				highlightingManager.initialiseDefaultColors();

 				refreshText();

 			}

-			

+

 		});

-		

+

 		highlightingManager.getPreferenceStore().addPropertyChangeListener(event -> {

 			if (highlightingManager.isColorPreference(event.getProperty())) {

 				refreshText();

 			}

 		});

-		

+

 		outlinePage = createOutlinePage();

-		

-		

+

 		final long delay = 1000;

-		

+

 		parseModuleJob = new Job("Parsing module") {

-			

+

 			protected int status = -1;

-			

+

 			@Override

 			protected IStatus run(IProgressMonitor monitor) {

-				

+

 				if (!isClosed()) {

 					int textHashCode = getText().hashCode();

 					if (status != textHashCode) {

 						parseModule();

 						status = textHashCode;

 					}

-					

+

 					this.schedule(delay);

 				}

-				

+

 				return Status.OK_STATUS;

 			}

 		};

-		

+

 		parseModuleJob.setSystem(true);

 		parseModuleJob.schedule(delay);

-	

+

 	}

-	

+

 	public boolean isClosed() {

 		return this.getDocumentProvider() == null;

 	}

-	

+

 	public String getText() {

-		return this.getDocumentProvider().getDocument(

-				this.getEditorInput()).get();

+		return this.getDocumentProvider().getDocument(this.getEditorInput()).get();

 	}

-	

+

 	public void parseModule() {

-		

-		// Return early if the file is opened in an unexpected editor (e.g. in a Subclipse RemoteFileEditor)

-		if (!(getEditorInput() instanceof FileEditorInput)) return;

-		

+

+		// Return early if the file is opened in an unexpected editor (e.g. in a

+		// Subclipse RemoteFileEditor)

+		if (!(getEditorInput() instanceof FileEditorInput))

+			return;

+

 		FileEditorInput fileInputEditor = (FileEditorInput) getEditorInput();

 		IFile file = fileInputEditor.getFile();

-		

+

 		final IModule module = createModule();

-		final IDocument doc = this.getDocumentProvider().getDocument(

-				this.getEditorInput());

-		

+		final IDocument doc = this.getDocumentProvider().getDocument(this.getEditorInput());

+

 		// Replace tabs with spaces to match

 		// column numbers produced by the parser

 		String code = doc.get();

 		code = code.replaceAll("\t", " ");

-		

+

 		try {

 			module.parse(code, new File(file.getLocation().toOSString()));

 		} catch (Exception e) {

-			

+

 		}

-		

+

 		// Update problem markers

 		// TODO: Update problem markers in all referenced files

 		try {

@@ -398,98 +394,104 @@
 			for (String markerType : getMarkerTypes()) {

 				file.deleteMarkers(markerType, true, IResource.DEPTH_INFINITE);

 			}

-			

+

 			// Create markers for parse problems

 			for (ParseProblem problem : module.getParseProblems()) {

 				Map<String, Object> attr = new HashMap<>();

 				attr.put(IMarker.LINE_NUMBER, problem.getLine());

-				attr.put(IMarker.MESSAGE, problem.getReason());				

+				attr.put(IMarker.MESSAGE, problem.getReason());

 				int markerSeverity;

 				if (problem.getSeverity() == ParseProblem.ERROR) {

 					markerSeverity = IMarker.SEVERITY_ERROR;

-				}

-				else {

+				} else {

 					markerSeverity = IMarker.SEVERITY_WARNING;

 				}

 				attr.put(IMarker.SEVERITY, markerSeverity);

 				MarkerUtilities.createMarker(file, attr, AbstractModuleEditor.PROBLEM_MARKER);

 			}

-			

+

 			// If the module has no parse problems, pass it on to the validators

 			// Use try/catch to protect against unexpected exceptions in the validators

 			if (module.getParseProblems().isEmpty()) {

-				

+

 				try {

-					if (EpsilonCommonsPlugin.getDefault().getPreferenceStore().getBoolean(EpsilonPreferencePage.ENABLE_STATIC_ANALYSIS)) {

+					if (EpsilonCommonsPlugin.getDefault().getPreferenceStore()

+							.getBoolean(EpsilonPreferencePage.ENABLE_STATIC_ANALYSIS)) {

 						if (module instanceof IEolModule) {

 							IEolCompilationContext compilationContext = ((IEolModule) module).getCompilationContext();

-							if (compilationContext != null) compilationContext.setModelFactory(new ModelTypeExtensionFactory());

+							if (compilationContext != null)

+								compilationContext.setModelFactory(new ModelTypeExtensionFactory());

 						}

 						createMarkers(module.compile(), doc, file, AbstractModuleEditor.PROBLEM_MARKER);

 					}

-					

-					for (IModuleValidator validator : ModuleValidatorExtensionPointManager.getDefault().getExtensions()) {

-						String markerType = (validator.getMarkerType() == null ? AbstractModuleEditor.PROBLEM_MARKER : validator.getMarkerType());

+

+					for (IModuleValidator validator : ModuleValidatorExtensionPointManager.getDefault()

+							.getExtensions()) {

+						String markerType = (validator.getMarkerType() == null ? AbstractModuleEditor.PROBLEM_MARKER

+								: validator.getMarkerType());

 						createMarkers(validator.validate(module), doc, file, markerType);

 					}

+				} catch (Exception ex) {

+					LogUtil.log(ex);

 				}

-				catch (Exception ex) { LogUtil.log(ex); }

-				

+

 			}

-			

-		} catch (CoreException e1) {}

-		

+

+		} catch (CoreException e1) {

+		}

+

 		if (module != null && module.getParseProblems().size() == 0) {

 			notifyModuleParsedListeners(module);

 		}

-		

+

 	}

-	

-	private void createMarkers(List<ModuleMarker> moduleMarkers, IDocument doc, IFile file, String markerType) throws BadLocationException, CoreException {

-		if (moduleMarkers == null) return;

-		

+

+	private void createMarkers(List<ModuleMarker> moduleMarkers, IDocument doc, IFile file, String markerType)

+			throws BadLocationException, CoreException {

+		if (moduleMarkers == null)

+			return;

+

 		for (ModuleMarker moduleMarker : moduleMarkers) {

 			Map<String, Object> attr = new HashMap<>();

 			Region region = moduleMarker.getRegion();

-			int startOffset = doc.getLineOffset(region.getStart().getLine()-1) + region.getStart().getColumn();

-			int endOffset = doc.getLineOffset(region.getEnd().getLine()-1) + region.getEnd().getColumn();

+			int startOffset = doc.getLineOffset(region.getStart().getLine() - 1) + region.getStart().getColumn();

+			int endOffset = doc.getLineOffset(region.getEnd().getLine() - 1) + region.getEnd().getColumn();

 			attr.put(IMarker.CHAR_START, startOffset);

 			attr.put(IMarker.CHAR_END, endOffset);

 			attr.put(IMarker.MESSAGE, moduleMarker.getMessage());

 			if (moduleMarker.getSeverity() == Severity.Error) {

 				attr.put(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);

-			}

-			else if (moduleMarker.getSeverity() == Severity.Warning) {

+			} else if (moduleMarker.getSeverity() == Severity.Warning) {

 				attr.put(IMarker.SEVERITY, IMarker.SEVERITY_WARNING);

-			}

-			else {

+			} else {

 				attr.put(IMarker.SEVERITY, IMarker.SEVERITY_INFO);

 			}

-			

+

 			MarkerUtilities.createMarker(file, attr, markerType);

 		}

 	}

-	

+

 	private Collection<String> getMarkerTypes() {

 		final Set<String> markerTypes = new HashSet<>();

 		markerTypes.add(AbstractModuleEditor.PROBLEM_MARKER);

-		

+

 		for (IModuleValidator validator : ModuleValidatorExtensionPointManager.getDefault().getExtensions()) {

 			markerTypes.add(validator.getMarkerType());

 		}

 		return markerTypes;

 	}

-	

+

 	@Override

 	public void doSave(IProgressMonitor progressMonitor) {

 		super.doSave(progressMonitor);

-		if (!supportsDirtyTextParsing()) parseModule();

+		if (!supportsDirtyTextParsing())

+			parseModule();

 	}

-	

+

 	protected abstract boolean supportsHyperlinks();

-	

+

 	protected abstract boolean supportsDirtyTextParsing();

-	

+

 	public Color getBackgroundColor() {

 		return backgroundColor;

 	}

@@ -497,71 +499,64 @@
 	public void setBackgroundColor(Color backgroundColor) {

 		this.backgroundColor = backgroundColor;

 	}

-	

+

 	@Override

 	public void close(boolean save) {

 		parseModuleJob.cancel();

 		super.close(save);

 	}

-	

+

 	public final List<Template> getTemplates() {

-		

+

 		List<Template> templates = new ArrayList<>();

-		

+

 		for (IAbstractModuleEditorTemplateContributor contributor : templateContributors) {

 			templates.addAll(contributor.getTemplates());

 		}

-		

+

 		return templates;

 	}

-	

-	private static final String CONTENTASSIST_PROPOSAL_ID = "org.eclipse.common.dt.editor.AbsractModuleEditor.ContentAssistProposal"; 

-	

+

+	private static final String CONTENTASSIST_PROPOSAL_ID = "org.eclipse.common.dt.editor.AbsractModuleEditor.ContentAssistProposal";

+	private static final String TOGGLE_COMMENT_ID = "org.eclipse.epsilon.common.dt.editor.AbsractModuleEditor.ToggleComment";

+

 	@Override

 	protected void createActions() {

-	   super.createActions();

+		super.createActions();

 

-	   // This action will fire a CONTENTASSIST_PROPOSALS operation

-	   // when executed

-	   IAction action = 

-	      new TextOperationAction(new ResourceBundle(){

+		// This action will fire a CONTENTASSIST_PROPOSALS operation

+		// when executed

+		IAction action = new TextOperationAction(new EmptyResourceBundle(), "ContentAssistProposal", this,

+				ISourceViewer.CONTENTASSIST_PROPOSALS);

+		action.setActionDefinitionId(CONTENTASSIST_PROPOSAL_ID);

+		setAction(CONTENTASSIST_PROPOSAL_ID, action);

 

-			@Override

-			public Enumeration<String> getKeys() {

-				// TODO Auto-generated method stub

-				return null;

-			}

+		// Tell the editor to execute this action

+		// when Ctrl+Spacebar is pressed

+		setActionActivationCode(CONTENTASSIST_PROPOSAL_ID, ' ', -1, SWT.CTRL);

 

-			@Override

-			protected Object handleGetObject(String key) {

-				// TODO Auto-generated method stub

-				return null;

-			}},

-	      "ContentAssistProposal", this, ISourceViewer.CONTENTASSIST_PROPOSALS);

-	   action.setActionDefinitionId(CONTENTASSIST_PROPOSAL_ID);

-

-	   // Tell the editor about this new action

-	   setAction(CONTENTASSIST_PROPOSAL_ID, action);

-

-	   // Tell the editor to execute this action 

-	   // when Ctrl+Spacebar is pressed

-	   setActionActivationCode(CONTENTASSIST_PROPOSAL_ID,' ', -1, SWT.CTRL);

+		// Set up the toggle comment action

+		ToggleCommentAction toggleCommentAction = new ToggleCommentAction(new EmptyResourceBundle(), "ToggleComment",

+				this);

+		toggleCommentAction.setActionDefinitionId(TOGGLE_COMMENT_ID);

+		toggleCommentAction.configure(getSourceViewer(), getSourceViewerConfiguration());

+		setAction(TOGGLE_COMMENT_ID, toggleCommentAction);

 	}

 

 	public EpsilonHighlightingManager getHighlightingManager() {

 		return highlightingManager;

 	}

-	

+

 	private void refreshText() {

 		ISourceViewer viewer = getSourceViewer();

 		if (!(viewer instanceof ISourceViewerExtension2))

 			return;

 

-		((ISourceViewerExtension2)viewer).unconfigure();

+		((ISourceViewerExtension2) viewer).unconfigure();

 		setSourceViewerConfiguration(createSourceViewerConfiguration());

 		viewer.configure(getSourceViewerConfiguration());

 	}

-	

+

 	@Override

 	public boolean isDirty() {

 		// TODO add logic to fix bug 376294

diff --git a/plugins/org.eclipse.epsilon.common.dt/src/org/eclipse/epsilon/common/dt/editor/AbstractModuleEditorSourceViewerConfiguration.java b/plugins/org.eclipse.epsilon.common.dt/src/org/eclipse/epsilon/common/dt/editor/AbstractModuleEditorSourceViewerConfiguration.java
index e964de1..8f5f44f 100644
--- a/plugins/org.eclipse.epsilon.common.dt/src/org/eclipse/epsilon/common/dt/editor/AbstractModuleEditorSourceViewerConfiguration.java
+++ b/plugins/org.eclipse.epsilon.common.dt/src/org/eclipse/epsilon/common/dt/editor/AbstractModuleEditorSourceViewerConfiguration.java
@@ -33,10 +33,9 @@
 public class AbstractModuleEditorSourceViewerConfiguration extends SourceViewerConfiguration {

 	

 	protected AbstractModuleEditor editor = null;

-	

 	protected AbstractModuleEditorScanner scanner;

 	protected AbstractModuleEditorNormalFontScanner commentScanner;

-	//protected AbstractModuleEditorNormalFontScanner stringScanner;

+	protected String[] defaultPrefixes = new String[] {"//"};

 	

 	public AbstractModuleEditorSourceViewerConfiguration(AbstractModuleEditor editor) {

 		this.editor = editor;

@@ -140,4 +139,9 @@
 	public AbstractModuleEditorNormalFontScanner getCommentScanner() {

 		return commentScanner;

 	}

+	

+	@Override

+	public String[] getDefaultPrefixes(ISourceViewer sourceViewer, String contentType) {

+		return defaultPrefixes;

+	}

 }

diff --git a/plugins/org.eclipse.epsilon.common.dt/src/org/eclipse/epsilon/common/dt/editor/EmptyResourceBundle.java b/plugins/org.eclipse.epsilon.common.dt/src/org/eclipse/epsilon/common/dt/editor/EmptyResourceBundle.java
new file mode 100644
index 0000000..5725856
--- /dev/null
+++ b/plugins/org.eclipse.epsilon.common.dt/src/org/eclipse/epsilon/common/dt/editor/EmptyResourceBundle.java
@@ -0,0 +1,18 @@
+package org.eclipse.epsilon.common.dt.editor;
+
+import java.util.Enumeration;
+import java.util.ResourceBundle;
+
+public class EmptyResourceBundle extends ResourceBundle {
+
+	@Override
+	protected Object handleGetObject(String key) {
+		return null;
+	}
+
+	@Override
+	public Enumeration<String> getKeys() {
+		return null;
+	}
+
+}
diff --git a/plugins/org.eclipse.epsilon.common.dt/src/org/eclipse/epsilon/common/dt/editor/ToggleCommentAction.java b/plugins/org.eclipse.epsilon.common.dt/src/org/eclipse/epsilon/common/dt/editor/ToggleCommentAction.java
new file mode 100644
index 0000000..3916124
--- /dev/null
+++ b/plugins/org.eclipse.epsilon.common.dt/src/org/eclipse/epsilon/common/dt/editor/ToggleCommentAction.java
@@ -0,0 +1,311 @@
+package org.eclipse.epsilon.common.dt.editor;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.ResourceBundle;
+
+import org.eclipse.epsilon.common.dt.util.LogUtil;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextOperationTarget;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.TextUtilities;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.text.source.SourceViewerConfiguration;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.swt.custom.BusyIndicator;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.ui.texteditor.ResourceAction;
+import org.eclipse.ui.texteditor.TextEditorAction;
+
+
+/**
+ * An action which toggles comment prefixes on the selected lines.
+ * Copied/adapted from org.eclipse.jdt.internal.ui.javaeditor.ToggleCommentAction
+ *
+ * @since 2.3
+ */
+public final class ToggleCommentAction extends TextEditorAction {
+
+	/** The text operation target */
+	private ITextOperationTarget fOperationTarget;
+	/** The document partitioning */
+	private String fDocumentPartitioning;
+	/** The comment prefixes */
+	private Map<String, String[]> fPrefixesMap;
+
+	/**
+	 * Creates and initializes the action for the given text editor. The action
+	 * configures its visual representation from the given resource bundle.
+	 *
+	 * @param bundle the resource bundle
+	 * @param prefix a prefix to be prepended to the various resource keys
+	 *   (described in <code>ResourceAction</code> constructor), or
+	 *   <code>null</code> if none
+	 * @param editor the text editor
+	 * @see ResourceAction#ResourceAction(ResourceBundle, String, int)
+	 */
+	public ToggleCommentAction(ResourceBundle bundle, String prefix, ITextEditor editor) {
+		super(bundle, prefix, editor);
+	}
+
+	/**
+	 * Implementation of the <code>IAction</code> prototype. Checks if the selected
+	 * lines are all commented or not and uncomments/comments them respectively.
+	 */
+	@Override
+	public void run() {
+		
+		if (fOperationTarget == null || fDocumentPartitioning == null || fPrefixesMap == null)
+			return;
+
+		ITextEditor editor= getTextEditor();
+		if (editor == null)
+			return;
+
+		if (!validateEditorInputState())
+			return;
+
+		final int operationCode;
+		if (isSelectionCommented(editor.getSelectionProvider().getSelection()))
+			operationCode= ITextOperationTarget.STRIP_PREFIX;
+		else
+			operationCode= ITextOperationTarget.PREFIX;
+
+		Shell shell= editor.getSite().getShell();
+		if (!fOperationTarget.canDoOperation(operationCode)) {
+			return;
+		}
+
+		Display display= null;
+		if (shell != null && !shell.isDisposed())
+			display= shell.getDisplay();
+
+		BusyIndicator.showWhile(display, new Runnable() {
+			@Override
+			public void run() {
+				fOperationTarget.doOperation(operationCode);
+			}
+		});
+	}
+
+	/**
+	 * Is the given selection single-line commented?
+	 *
+	 * @param selection Selection to check
+	 * @return <code>true</code> iff all selected lines are commented
+	 */
+	private boolean isSelectionCommented(ISelection selection) {
+		if (!(selection instanceof ITextSelection))
+			return false;
+
+		ITextSelection textSelection= (ITextSelection) selection;
+		if (textSelection.getStartLine() < 0 || textSelection.getEndLine() < 0)
+			return false;
+
+		IDocument document= getTextEditor().getDocumentProvider().getDocument(getTextEditor().getEditorInput());
+
+		try {
+
+			IRegion block= getTextBlockFromSelection(textSelection, document);
+			ITypedRegion[] regions= TextUtilities.computePartitioning(document, fDocumentPartitioning, block.getOffset(), block.getLength(), false);
+
+			int[] lines= new int[regions.length * 2]; // [startline, endline, startline, endline, ...]
+			for (int i= 0, j= 0; i < regions.length; i++, j+= 2) {
+				// start line of region
+				lines[j]= getFirstCompleteLineOfRegion(regions[i], document);
+				// end line of region
+				int length= regions[i].getLength();
+				int offset= regions[i].getOffset() + length;
+				if (length > 0)
+					offset--;
+				lines[j + 1]= (lines[j] == -1 ? -1 : document.getLineOfOffset(offset));
+			}
+
+			// Perform the check
+			for (int i= 0, j= 0; i < regions.length; i++, j += 2) {
+				String[] prefixes= fPrefixesMap.get(regions[i].getType());
+				if (prefixes != null && prefixes.length > 0 && lines[j] >= 0 && lines[j + 1] >= 0)
+					if (!isBlockCommented(lines[j], lines[j + 1], prefixes, document))
+						return false;
+			}
+
+			return true;
+
+		} catch (BadLocationException x) {
+			// should not happen
+			LogUtil.log(x);
+		}
+
+		return false;
+	}
+
+	/**
+	 * Creates a region describing the text block (something that starts at
+	 * the beginning of a line) completely containing the current selection.
+	 *
+	 * @param selection The selection to use
+	 * @param document The document
+	 * @return the region describing the text block comprising the given selection
+	 */
+	private IRegion getTextBlockFromSelection(ITextSelection selection, IDocument document) {
+
+		try {
+			IRegion line= document.getLineInformationOfOffset(selection.getOffset());
+			int length= selection.getLength() == 0 ? line.getLength() : selection.getLength() + (selection.getOffset() - line.getOffset());
+			return new Region(line.getOffset(), length);
+
+		} catch (BadLocationException x) {
+			// should not happen
+			LogUtil.log(x);
+		}
+
+		return null;
+	}
+
+	/**
+	 * Returns the index of the first line whose start offset is in the given text range.
+	 *
+	 * @param region the text range in characters where to find the line
+	 * @param document The document
+	 * @return the first line whose start index is in the given range, -1 if there is no such line
+	 */
+	private int getFirstCompleteLineOfRegion(IRegion region, IDocument document) {
+
+		try {
+
+			final int startLine= document.getLineOfOffset(region.getOffset());
+
+			int offset= document.getLineOffset(startLine);
+			if (offset >= region.getOffset())
+				return startLine;
+
+			final int nextLine= startLine + 1;
+			if (nextLine == document.getNumberOfLines())
+				return -1;
+
+			offset= document.getLineOffset(nextLine);
+			return (offset > region.getOffset() + region.getLength() ? -1 : nextLine);
+
+		} catch (BadLocationException x) {
+			// should not happen
+			LogUtil.log(x);
+		}
+
+		return -1;
+	}
+
+	/**
+	 * Determines whether each line is prefixed by one of the prefixes.
+	 *
+	 * @param startLine Start line in document
+	 * @param endLine End line in document
+	 * @param prefixes Possible comment prefixes
+	 * @param document The document
+	 * @return <code>true</code> iff each line from <code>startLine</code>
+	 *             to and including <code>endLine</code> is prepended by one
+	 *             of the <code>prefixes</code>, ignoring whitespace at the
+	 *             begin of line
+	 */
+	private boolean isBlockCommented(int startLine, int endLine, String[] prefixes, IDocument document) {
+
+		try {
+
+			// check for occurrences of prefixes in the given lines
+			for (int i= startLine; i <= endLine; i++) {
+
+				IRegion line= document.getLineInformation(i);
+				String text= document.get(line.getOffset(), line.getLength());
+
+				int[] found= TextUtilities.indexOf(prefixes, text, 0);
+
+				if (found[0] == -1)
+					// found a line which is not commented
+					return false;
+
+				String s= document.get(line.getOffset(), found[0]);
+				s= s.trim();
+				if (s.length() != 0)
+					// found a line which is not commented
+					return false;
+
+			}
+
+			return true;
+
+		} catch (BadLocationException x) {
+			// should not happen
+			LogUtil.log(x);
+		}
+
+		return false;
+	}
+
+	/**
+	 * Implementation of the <code>IUpdate</code> prototype method discovers
+	 * the operation through the current editor's
+	 * <code>ITextOperationTarget</code> adapter, and sets the enabled state
+	 * accordingly.
+	 */
+	@Override
+	public void update() {
+		super.update();
+
+		if (!canModifyEditor()) {
+			setEnabled(false);
+			return;
+		}
+
+		ITextEditor editor= getTextEditor();
+		if (fOperationTarget == null && editor != null)
+			fOperationTarget= editor.getAdapter(ITextOperationTarget.class);
+
+		boolean isEnabled= (fOperationTarget != null && fOperationTarget.canDoOperation(ITextOperationTarget.PREFIX) && fOperationTarget.canDoOperation(ITextOperationTarget.STRIP_PREFIX));
+		setEnabled(isEnabled);
+	}
+
+	/*
+	 * @see TextEditorAction#setEditor(ITextEditor)
+	 */
+	@Override
+	public void setEditor(ITextEditor editor) {
+		super.setEditor(editor);
+		fOperationTarget= null;
+	}
+
+	public void configure(ISourceViewer sourceViewer, SourceViewerConfiguration configuration) {
+		fPrefixesMap= null;
+
+		String[] types= configuration.getConfiguredContentTypes(sourceViewer);
+		Map<String, String[]> prefixesMap= new HashMap<>(types.length);
+		for (String type : types) {
+			String[] prefixes= configuration.getDefaultPrefixes(sourceViewer, type);
+			if (prefixes != null && prefixes.length > 0) {
+				int emptyPrefixes= 0;
+				for (String prefix : prefixes) {
+					if (prefix.length() == 0) {
+						emptyPrefixes++;
+					}
+				}
+				if (emptyPrefixes > 0) {
+					String[] nonemptyPrefixes= new String[prefixes.length - emptyPrefixes];
+					for (int j= 0, k= 0; j < prefixes.length; j++) {
+						String prefix= prefixes[j];
+						if (prefix.length() != 0) {
+							nonemptyPrefixes[k]= prefix;
+							k++;
+						}
+					}
+					prefixes= nonemptyPrefixes;
+				}
+				prefixesMap.put(type, prefixes);
+			}
+		}
+		fDocumentPartitioning= configuration.getConfiguredDocumentPartitioning(sourceViewer);
+		fPrefixesMap= prefixesMap;
+	}
+}