/******************************************************************************* * Copyright (c) 2010, 2011 IBM Corporation and others. * 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: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.ui.propertiesfileeditor; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.eclipse.swt.graphics.Point; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.BadPartitioningException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IDocumentExtension3; import org.eclipse.jface.text.ITypedRegion; import org.eclipse.jface.text.contentassist.ICompletionProposal; import org.eclipse.jface.text.quickassist.IQuickAssistInvocationContext; import org.eclipse.jface.text.source.Annotation; import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.jface.text.source.TextInvocationContext; import org.eclipse.ui.texteditor.spelling.SpellingCorrectionProcessor; import org.eclipse.ltk.core.refactoring.NullChange; import org.eclipse.jdt.ui.text.java.CompletionProposalComparator; import org.eclipse.jdt.internal.ui.JavaPlugin; import org.eclipse.jdt.internal.ui.text.correction.CorrectionMessages; import org.eclipse.jdt.internal.ui.text.correction.proposals.ChangeCorrectionProposal; /** * The properties file correction processor. Clients can set pre-computed proposals, and if set the * processor returns only these pre-computed proposals. * * @since 3.7 */ public class PropertiesCorrectionProcessor implements org.eclipse.jface.text.quickassist.IQuickAssistProcessor { private String fErrorMessage; private SpellingCorrectionProcessor fSpellingCorrectionProcessor; private ICompletionProposal[] fPreComputedProposals; public PropertiesCorrectionProcessor() { fSpellingCorrectionProcessor= new SpellingCorrectionProcessor(); } /* * @see IContentAssistProcessor#computeCompletionProposals(ITextViewer, int) */ public ICompletionProposal[] computeQuickAssistProposals(IQuickAssistInvocationContext quickAssistContext) { ISourceViewer viewer= quickAssistContext.getSourceViewer(); int length= viewer != null ? viewer.getSelectedRange().y : 0; TextInvocationContext context= new TextInvocationContext(viewer, quickAssistContext.getOffset(), length); fErrorMessage= null; ICompletionProposal[] res= null; if (fPreComputedProposals != null) { res= fPreComputedProposals; } else { try { List<ICompletionProposal> proposals= new ArrayList<ICompletionProposal>(); ICompletionProposal[] spellingProposals= fSpellingCorrectionProcessor.computeQuickAssistProposals(quickAssistContext); if (spellingProposals.length > 1) { for (int i= 0; i < spellingProposals.length; i++) { proposals.add(spellingProposals[i]); } } ICompletionProposal[] assists= collectAssists(context); if (assists != null) { for (int i= 0; i < assists.length; i++) { proposals.add(assists[i]); } } res= proposals.toArray(new ICompletionProposal[proposals.size()]); } catch (BadLocationException e) { fErrorMessage= CorrectionMessages.JavaCorrectionProcessor_error_quickassist_message; JavaPlugin.log(e); } catch (BadPartitioningException e) { fErrorMessage= CorrectionMessages.JavaCorrectionProcessor_error_quickassist_message; JavaPlugin.log(e); } } if (res == null || res.length == 0) { return new ICompletionProposal[] { new ChangeCorrectionProposal(CorrectionMessages.NoCorrectionProposal_description, new NullChange(""), 0, null) }; //$NON-NLS-1$ } if (res.length > 1) { Arrays.sort(res, new CompletionProposalComparator()); } fPreComputedProposals= null; return res; } private static ICompletionProposal[] collectAssists(IQuickAssistInvocationContext invocationContext) throws BadLocationException, BadPartitioningException { ISourceViewer sourceViewer= invocationContext.getSourceViewer(); IDocument document= sourceViewer.getDocument(); Point selectedRange= sourceViewer.getSelectedRange(); int selectionOffset= selectedRange.x; int selectionLength= selectedRange.y; int proposalOffset; int proposalLength; String text; if (selectionLength == 0) { if (selectionOffset != document.getLength()) { char ch= document.getChar(selectionOffset); if (ch == '=' || ch == ':') { //see PropertiesFilePartitionScanner() return null; } } ITypedRegion partition= null; if (document instanceof IDocumentExtension3) partition= ((IDocumentExtension3)document).getPartition(IPropertiesFilePartitions.PROPERTIES_FILE_PARTITIONING, invocationContext.getOffset(), false); if (partition == null) return null; String type= partition.getType(); if (!(type.equals(IPropertiesFilePartitions.PROPERTY_VALUE) || type.equals(IDocument.DEFAULT_CONTENT_TYPE))) { return null; } proposalOffset= partition.getOffset(); proposalLength= partition.getLength(); text= document.get(proposalOffset, proposalLength); if (type.equals(IPropertiesFilePartitions.PROPERTY_VALUE)) { text= text.substring(1); //see PropertiesFilePartitionScanner() proposalOffset++; proposalLength--; } } else { proposalOffset= selectionOffset; proposalLength= selectionLength; text= document.get(proposalOffset, proposalLength); } if (PropertiesFileEscapes.containsUnescapedBackslash(text)) return new ICompletionProposal[] { new EscapeBackslashCompletionProposal(PropertiesFileEscapes.escape(text, false, true, false), proposalOffset, proposalLength, true) }; if (PropertiesFileEscapes.containsEscapedBackslashes(text)) return new ICompletionProposal[] { new EscapeBackslashCompletionProposal(PropertiesFileEscapes.unescapeBackslashes(text), proposalOffset, proposalLength, false) }; return null; } /* * @see IContentAssistProcessor#getErrorMessage() */ public String getErrorMessage() { return fErrorMessage; } /* * @see org.eclipse.jface.text.quickassist.IQuickAssistProcessor#canFix(org.eclipse.jface.text.source.Annotation) */ public boolean canFix(Annotation annotation) { return fSpellingCorrectionProcessor.canFix(annotation); } /* * @see org.eclipse.jface.text.quickassist.IQuickAssistProcessor#canAssist(org.eclipse.jface.text.quickassist.IQuickAssistInvocationContext) */ public boolean canAssist(IQuickAssistInvocationContext invocationContext) { try { return collectAssists(invocationContext) != null; } catch (BadLocationException e) { JavaPlugin.log(e); } catch (BadPartitioningException e) { JavaPlugin.log(e); } return false; } /** * Sets the pre-computed proposals. * * @param preComputedProposals the pre-computed proposals */ public void setProposals(ICompletionProposal[] preComputedProposals) { fPreComputedProposals= preComputedProposals; } }