/******************************************************************************* * Copyright 2011 Google Inc. All Rights Reserved. * * 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 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *******************************************************************************/ package com.google.gwt.eclipse.core.editors.java; import com.google.gdt.eclipse.core.formatter.IDocumentCloner; import com.google.gdt.eclipse.core.formatter.IndependentMultiPassContentFormatter; import com.google.gwt.eclipse.core.GWTPluginLog; import com.google.gwt.eclipse.core.editors.java.contentassist.JsniCompletionProcessor; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.internal.ui.text.JavaCompositeReconcilingStrategy; import org.eclipse.jdt.internal.ui.text.JavaReconciler; import org.eclipse.jdt.internal.ui.text.java.JavaFormattingStrategy; import org.eclipse.jdt.internal.ui.text.spelling.JavaSpellingReconcileStrategy; import org.eclipse.jdt.ui.text.IColorManager; import org.eclipse.jdt.ui.text.IJavaPartitions; import org.eclipse.jdt.ui.text.JavaSourceViewerConfiguration; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.text.Document; import org.eclipse.jface.text.IAutoEditStrategy; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.TextAttribute; 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.formatter.IContentFormatter; 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.IReconcilingStrategy; import org.eclipse.jface.text.rules.DefaultDamagerRepairer; import org.eclipse.jface.text.rules.Token; import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.ui.texteditor.ITextEditor; import java.util.Map; /** * Provides custom editor behavior for the GWT-specific Java editor. */ @SuppressWarnings("restriction") public class GWTSourceViewerConfiguration extends JavaSourceViewerConfiguration { /** * Clones a document representing a .java source file. The clone will have the * same text and partitioning (GWTPartitions.GWT_PARTITIONING and * IJavaPartitions.JAVA_PARTITIONING) as the original. */ private static final IDocumentCloner JAVA_DOCUMENT_CLONER = new IDocumentCloner() { public IDocument clone(IDocument original) { IDocument clone = new Document(original.get()); new GWTDocumentSetupParticipant().setup(clone); return clone; } public void release(IDocument clone) { // Nothing to release } }; private final JsniScanner jsniScanner; public GWTSourceViewerConfiguration(IColorManager colorManager, IPreferenceStore preferenceStore, ITextEditor editor) { /* * We're passing null for the partitioning here, and will instead provide it * on demand in our getConfiguredDocumentPartitioning override. This allows * us to emulate the Java editor by using Java partitioning for .java files * in non-GWT projects. If we always used GWT partitioning, non-GWT .java * files would end up with no syntax coloring when opened by the GWT editor * (since GWT partitioning is only applied within GWT projects). */ super(colorManager, preferenceStore, editor, null); jsniScanner = new JsniScanner(colorManager); jsniScanner.setDefaultReturnToken(new Token(new TextAttribute( colorManager.getColor(JsniColorConstants.JSNI_DEFAULT)))); } @Override public IAutoEditStrategy[] getAutoEditStrategies(ISourceViewer sourceViewer, String contentType) { if (GWTPartitions.JSNI_METHOD.equals(contentType)) { // Get project's formatting settings IJavaProject javaProject = ((GWTJavaEditor) getEditor()).getInputJavaProject(); Map<?, ?> prefs = (javaProject != null ? javaProject.getOptions(true) : JavaCore.getOptions()); return new IAutoEditStrategy[] {new JsniAutoEditStrategy(prefs)}; } return super.getAutoEditStrategies(sourceViewer, contentType); } @Override public String[] getConfiguredContentTypes(ISourceViewer sourceViewer) { // Include all native Java content types as well as custom types like JSNI String[] javaContentTypes = super.getConfiguredContentTypes(sourceViewer); String[] jsniContentTypes = {GWTPartitions.JSNI_METHOD}; String[] allContentTypes = new String[javaContentTypes.length + jsniContentTypes.length]; System.arraycopy(javaContentTypes, 0, allContentTypes, 0, javaContentTypes.length); System.arraycopy(jsniContentTypes, 0, allContentTypes, javaContentTypes.length, jsniContentTypes.length); return allContentTypes; } @Override public String getConfiguredDocumentPartitioning(ISourceViewer sourceViewer) { try { ITextEditor editor = getEditor(); return ((GWTJavaEditor) editor).getInputPartitioning(); } catch (Exception e) { GWTPluginLog.logError(e); return IJavaPartitions.JAVA_PARTITIONING; } } @Override public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) { ContentAssistant assistant = (ContentAssistant) super.getContentAssistant(sourceViewer); ICompilationUnit cu = ((GWTJavaEditor) getEditor()).getCompilationUnit(); IContentAssistProcessor processor = new JsniCompletionProcessor(cu); assistant.setContentAssistProcessor(processor, GWTPartitions.JSNI_METHOD); return assistant; } @Override public IContentFormatter getContentFormatter(ISourceViewer sourceViewer) { IndependentMultiPassContentFormatter formatter = new IndependentMultiPassContentFormatter( getConfiguredDocumentPartitioning(sourceViewer), IDocument.DEFAULT_CONTENT_TYPE, JAVA_DOCUMENT_CLONER); formatter.setMasterStrategy(new JavaFormattingStrategy()); formatter.setSlaveStrategy2(new JsniFormattingStrategy(), GWTPartitions.JSNI_METHOD); return formatter; } @Override public IPresentationReconciler getPresentationReconciler( ISourceViewer sourceViewer) { PresentationReconciler reconciler = (PresentationReconciler) super.getPresentationReconciler(sourceViewer); DefaultDamagerRepairer dr = new DefaultDamagerRepairer(jsniScanner); reconciler.setDamager(dr, GWTPartitions.JSNI_METHOD); reconciler.setRepairer(dr, GWTPartitions.JSNI_METHOD); return reconciler; } @Override public IReconciler getReconciler(ISourceViewer sourceViewer) { JavaReconciler reconciler = (JavaReconciler) super.getReconciler(sourceViewer); if (reconciler != null) { try { JavaCompositeReconcilingStrategy strategy = (JavaCompositeReconcilingStrategy) reconciler.getReconcilingStrategy(IDocument.DEFAULT_CONTENT_TYPE); IReconcilingStrategy[] strategies = strategy.getReconcilingStrategies(); IReconcilingStrategy[] newStrategies = new IReconcilingStrategy[strategies.length]; for (int i = 0; i < strategies.length; i++) { if (strategies[i] instanceof JavaSpellingReconcileStrategy) { // Replace the default Java reconcile strategy with our own, which // will suppress spell checking within JSNI blocks newStrategies[i] = new GWTJavaSpellingReconcileStrategy( sourceViewer, getEditor()); } else { newStrategies[i] = strategies[i]; } } strategy.setReconcilingStrategies(newStrategies); } catch (Exception e) { // We're being defensive to ensure that we always return a reconciler GWTPluginLog.logError(e); } return reconciler; } return null; } }