You can subscribe to this list here.
| 2005 |
Jan
|
Feb
|
Mar
(41) |
Apr
(9) |
May
|
Jun
|
Jul
(39) |
Aug
(38) |
Sep
(135) |
Oct
(220) |
Nov
(75) |
Dec
(74) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2006 |
Jan
(44) |
Feb
(160) |
Mar
(49) |
Apr
(69) |
May
(40) |
Jun
(52) |
Jul
(47) |
Aug
(51) |
Sep
(19) |
Oct
(22) |
Nov
(36) |
Dec
(76) |
| 2007 |
Jan
(154) |
Feb
(165) |
Mar
(186) |
Apr
(143) |
May
(175) |
Jun
(133) |
Jul
(203) |
Aug
(177) |
Sep
(136) |
Oct
|
Nov
|
Dec
|
|
From: Christopher W. <caw...@us...> - 2006-02-22 20:04:18
|
Update of /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv4266/src/org/rubypeople/rdt/internal/ui/rubyeditor Modified Files: DocumentAdapter.java Log Message: complete task inside this file Index: DocumentAdapter.java =================================================================== RCS file: /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/DocumentAdapter.java,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** DocumentAdapter.java 8 Mar 2005 02:25:44 -0000 1.3 --- DocumentAdapter.java 22 Feb 2006 20:04:13 -0000 1.4 *************** *** 39,42 **** --- 39,43 ---- import org.rubypeople.rdt.core.IBufferChangedListener; import org.rubypeople.rdt.core.IOpenable; + import org.rubypeople.rdt.core.RubyModelException; import org.rubypeople.rdt.internal.ui.RubyPlugin; *************** *** 385,394 **** * @see IBuffer#save(IProgressMonitor, boolean) */ ! public void save(IProgressMonitor progress, boolean force) { try { if (fTextFileBuffer != null) fTextFileBuffer.commit(progress, force); } catch (CoreException e) { ! // TODO Retrhow as RubyModelException when we have it! ! e.printStackTrace(); } } --- 386,394 ---- * @see IBuffer#save(IProgressMonitor, boolean) */ ! public void save(IProgressMonitor progress, boolean force) throws RubyModelException { try { if (fTextFileBuffer != null) fTextFileBuffer.commit(progress, force); } catch (CoreException e) { ! throw new RubyModelException(e); } } |
|
From: Christopher W. <caw...@us...> - 2006-02-22 20:04:10
|
Update of /cvsroot/rubyeclipse/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv4101/src/org/rubypeople/rdt/internal/core Modified Files: CommitWorkingCopyOperation.java BecomeWorkingCopyOperation.java DiscardWorkingCopyOperation.java Log Message: extend RubyModelOperation Index: CommitWorkingCopyOperation.java =================================================================== RCS file: /cvsroot/rubyeclipse/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/CommitWorkingCopyOperation.java,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** CommitWorkingCopyOperation.java 11 Mar 2005 03:09:25 -0000 1.2 --- CommitWorkingCopyOperation.java 22 Feb 2006 20:04:05 -0000 1.3 *************** *** 18,28 **** import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.runtime.CoreException; - import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.jobs.ISchedulingRule; import org.rubypeople.rdt.core.IBuffer; import org.rubypeople.rdt.core.IRubyModelStatus; import org.rubypeople.rdt.core.IRubyModelStatusConstants; import org.rubypeople.rdt.core.IRubyScript; import org.rubypeople.rdt.core.RubyModelException; import org.rubypeople.rdt.internal.core.util.Util; --- 18,29 ---- import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.jobs.ISchedulingRule; import org.rubypeople.rdt.core.IBuffer; + import org.rubypeople.rdt.core.IRubyElement; import org.rubypeople.rdt.core.IRubyModelStatus; import org.rubypeople.rdt.core.IRubyModelStatusConstants; import org.rubypeople.rdt.core.IRubyScript; import org.rubypeople.rdt.core.RubyModelException; + import org.rubypeople.rdt.internal.core.util.Messages; import org.rubypeople.rdt.internal.core.util.Util; *************** *** 54,190 **** * of the folder containing the compilation unit). */ ! public class CommitWorkingCopyOperation { - private IRubyScript element; - private boolean force; - private IProgressMonitor progress; ! /** ! * Constructs an operation to commit the contents of a working copy to its ! * original compilation unit. ! */ ! public CommitWorkingCopyOperation(IRubyScript element, boolean force) { ! this.element = element; ! this.force = force; ! } ! /** ! * @exception RubyModelException ! * if setting the source of the original compilation unit ! * fails ! */ ! protected void executeOperation() throws RubyModelException { ! RubyScript workingCopy = getRubyScript(); ! IFile resource = (IFile) workingCopy.getResource(); ! IRubyScript primary = workingCopy.getPrimary(); ! boolean isPrimary = workingCopy.isPrimary(); ! if (isPrimary || (resource.isAccessible() && Util.isValidRubyScriptName(workingCopy.getElementName()))) { ! // force opening so that the delta builder can get the old info ! if (!isPrimary && !primary.isOpen()) { ! primary.open(null); ! } ! // save the cu ! IBuffer primaryBuffer = primary.getBuffer(); ! if (!isPrimary) { ! if (primaryBuffer == null) return; ! char[] primaryContents = primaryBuffer.getCharacters(); ! boolean hasSaved = false; ! try { ! IBuffer workingCopyBuffer = workingCopy.getBuffer(); ! if (workingCopyBuffer == null) return; ! primaryBuffer.setContents(workingCopyBuffer.getCharacters()); ! primaryBuffer.save(this.progress, this.force); ! primary.makeConsistent(this.progress); ! hasSaved = true; ! } finally { ! if (!hasSaved) { ! // restore original buffer contents since something went ! // wrong ! primaryBuffer.setContents(primaryContents); ! } ! } ! } else { ! // for a primary working copy no need to set the content of the ! // buffer again ! // FIXME Primary Buffer is null! ! primaryBuffer.save(this.progress, this.force); ! primary.makeConsistent(this.progress); ! } ! } else { ! // working copy on cu outside classpath OR resource doesn't exist ! // yet ! String encoding = null; ! try { ! encoding = resource.getCharset(); ! } catch (CoreException ce) { ! // use no encoding ! } ! String contents = workingCopy.getSource(); ! if (contents == null) return; ! try { ! byte[] bytes = encoding == null ? contents.getBytes() : contents.getBytes(encoding); ! ByteArrayInputStream stream = new ByteArrayInputStream(bytes); ! if (resource.exists()) { ! resource.setContents(stream, this.force ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY, null); ! } else { ! resource.create(stream, this.force, this.progress); ! } ! } catch (CoreException e) { ! throw new RubyModelException(e); ! } catch (UnsupportedEncodingException e) { ! throw new RubyModelException(e, IRubyModelStatusConstants.IO_EXCEPTION); ! } ! } ! // setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE); ! // make sure working copy is in sync ! workingCopy.updateTimeStamp((RubyScript) primary); ! workingCopy.makeConsistent(this.progress); ! } ! /** ! * Returns the compilation unit this operation is working on. ! */ ! protected RubyScript getRubyScript() { ! return (RubyScript) element; ! } ! protected ISchedulingRule getSchedulingRule() { ! IResource resource = element.getResource(); ! IWorkspace workspace = resource.getWorkspace(); ! if (resource.exists()) { return workspace.getRuleFactory().modifyRule(resource); } ! return workspace.getRuleFactory().createRule(resource); ! } ! /** ! * Possible failures: ! * <ul> ! * <li>INVALID_ELEMENT_TYPES - the compilation unit supplied to this ! * operation is not a working copy ! * <li>ELEMENT_NOT_PRESENT - the compilation unit the working copy is based ! * on no longer exists. ! * <li>UPDATE_CONFLICT - the original compilation unit has changed since ! * the working copy was created and the operation specifies no force ! * <li>READ_ONLY - the original compilation unit is in read-only mode ! * </ul> ! */ ! public IRubyModelStatus verify() { ! RubyScript cu = getRubyScript(); ! if (!cu.isWorkingCopy()) { return new RubyModelStatus(IRubyModelStatusConstants.INVALID_ELEMENT_TYPES, cu); } ! if (cu.hasResourceChanged() && !this.force) { return new RubyModelStatus(IRubyModelStatusConstants.UPDATE_CONFLICT); } ! // no read-only check, since some repository adapters can change the ! // flag on save ! // operation. ! return RubyModelStatus.VERIFIED_OK; ! } ! public void runOperation(IProgressMonitor monitor) throws RubyModelException { ! this.progress = monitor; ! executeOperation(); ! } } --- 55,227 ---- * of the folder containing the compilation unit). */ ! public class CommitWorkingCopyOperation extends RubyModelOperation { ! /** ! * Constructs an operation to commit the contents of a working copy to its ! * original compilation unit. ! */ ! public CommitWorkingCopyOperation(IRubyScript element, boolean force) { ! super(new IRubyElement[] { element}, force); ! } ! /** ! * @exception RubyModelException ! * if setting the source of the original compilation unit ! * fails ! */ ! protected void executeOperation() throws RubyModelException { ! try { ! beginTask(Messages.workingCopy_commit, 2); ! RubyScript workingCopy = getRubyScript(); ! IFile resource = (IFile) workingCopy.getResource(); ! if (resource == null) { ! // case of a working copy without a resource ! workingCopy.getBuffer().save(this.progressMonitor, this.force); ! return; ! } ! IRubyScript primary = workingCopy.getPrimary(); ! boolean isPrimary = workingCopy.isPrimary(); ! RubyElementDeltaBuilder deltaBuilder = null; ! ! boolean isIncluded = !Util.isExcluded(workingCopy); ! if (isPrimary ! || (isIncluded && resource.isAccessible() && Util ! .isValidRubyScriptName(workingCopy.getElementName()))) { ! // force opening so that the delta builder can get the old info ! if (!isPrimary && !primary.isOpen()) { ! primary.open(null); ! } ! // creates the delta builder (this remembers the content of the ! // cu) if: ! // - it is not excluded ! // - and it is not a primary or it is a non-consistent primary ! if (isIncluded && (!isPrimary || !workingCopy.isConsistent())) { ! deltaBuilder = new RubyElementDeltaBuilder(primary); ! } ! // save the cu ! IBuffer primaryBuffer = primary.getBuffer(); ! if (!isPrimary) { ! if (primaryBuffer == null) return; ! char[] primaryContents = primaryBuffer.getCharacters(); ! boolean hasSaved = false; ! try { ! IBuffer workingCopyBuffer = workingCopy.getBuffer(); ! if (workingCopyBuffer == null) return; ! primaryBuffer.setContents(workingCopyBuffer.getCharacters()); ! primaryBuffer.save(this.progressMonitor, this.force); ! primary.makeConsistent(this); ! hasSaved = true; ! } finally { ! if (!hasSaved) { ! // restore original buffer contents since something ! // went wrong ! primaryBuffer.setContents(primaryContents); ! } ! } ! } else { ! // for a primary working copy no need to set the content of ! // the buffer again ! primaryBuffer.save(this.progressMonitor, this.force); ! primary.makeConsistent(this); ! } ! } else { ! // working copy on cu outside classpath OR resource doesn't ! // exist yet ! String encoding = null; ! try { ! encoding = resource.getCharset(); ! } catch (CoreException ce) { ! // use no encoding ! } ! String contents = workingCopy.getSource(); ! if (contents == null) return; ! try { ! byte[] bytes = encoding == null ? contents.getBytes() : contents ! .getBytes(encoding); ! ByteArrayInputStream stream = new ByteArrayInputStream(bytes); ! if (resource.exists()) { ! resource.setContents(stream, this.force ? IResource.FORCE ! | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY, null); ! } else { ! resource.create(stream, this.force, this.progressMonitor); ! } ! } catch (CoreException e) { ! throw new RubyModelException(e); ! } catch (UnsupportedEncodingException e) { ! throw new RubyModelException(e, IRubyModelStatusConstants.IO_EXCEPTION); ! } ! } ! setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE); ! // make sure working copy is in sync ! workingCopy.updateTimeStamp((RubyScript) primary); ! workingCopy.makeConsistent(this); ! worked(1); ! // build the deltas ! if (deltaBuilder != null) { ! deltaBuilder.buildDeltas(); ! ! // add the deltas to the list of deltas created during this ! // operation ! if (deltaBuilder.delta != null) { ! addDelta(deltaBuilder.delta); ! } ! } ! worked(1); ! } finally { ! done(); ! } ! } ! ! /** ! * Returns the compilation unit this operation is working on. ! */ ! protected RubyScript getRubyScript() { ! return (RubyScript) getElementToProcess(); ! } ! ! protected ISchedulingRule getSchedulingRule() { ! IResource resource = getElementToProcess().getResource(); ! if (resource == null) return null; ! IWorkspace workspace = resource.getWorkspace(); ! if (resource.exists()) { ! return workspace.getRuleFactory().modifyRule(resource); ! } else { ! return workspace.getRuleFactory().createRule(resource); ! } ! } ! ! /** ! * Possible failures: ! * <ul> ! * <li>INVALID_ELEMENT_TYPES - the compilation unit supplied to this ! * operation is not a working copy ! * <li>ELEMENT_NOT_PRESENT - the compilation unit the working copy is based ! * on no longer exists. ! * <li>UPDATE_CONFLICT - the original compilation unit has changed since ! * the working copy was created and the operation specifies no force ! * <li>READ_ONLY - the original compilation unit is in read-only mode ! * </ul> ! */ ! public IRubyModelStatus verify() { ! RubyScript cu = getRubyScript(); ! if (!cu.isWorkingCopy()) { return new RubyModelStatus( ! IRubyModelStatusConstants.INVALID_ELEMENT_TYPES, cu); } ! if (cu.hasResourceChanged() && !this.force) { return new RubyModelStatus( ! IRubyModelStatusConstants.UPDATE_CONFLICT); } ! // no read-only check, since some repository adapters can change the ! // flag on save ! // operation. ! return RubyModelStatus.VERIFIED_OK; ! } } Index: BecomeWorkingCopyOperation.java =================================================================== RCS file: /cvsroot/rubyeclipse/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/BecomeWorkingCopyOperation.java,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** BecomeWorkingCopyOperation.java 4 Mar 2005 13:54:47 -0000 1.3 --- BecomeWorkingCopyOperation.java 22 Feb 2006 20:04:05 -0000 1.4 *************** *** 11,16 **** package org.rubypeople.rdt.internal.core; - import org.eclipse.core.runtime.IProgressMonitor; import org.rubypeople.rdt.core.IProblemRequestor; import org.rubypeople.rdt.core.RubyModelException; --- 11,17 ---- package org.rubypeople.rdt.internal.core; import org.rubypeople.rdt.core.IProblemRequestor; + import org.rubypeople.rdt.core.IRubyElement; + import org.rubypeople.rdt.core.IRubyElementDelta; import org.rubypeople.rdt.core.RubyModelException; *************** *** 19,67 **** * addition through a delta. */ ! public class BecomeWorkingCopyOperation { ! private RubyScript workingCopy; ! private IProgressMonitor monitor; ! private IProblemRequestor problemRequestor; ! /* ! * Creates a BecomeWorkingCopyOperation for the given working copy. ! * perOwnerWorkingCopies map is not null if the working copy is a shared ! * working copy. ! */ ! public BecomeWorkingCopyOperation(RubyScript workingCopy, IProblemRequestor problemRequestor) { ! this.workingCopy = workingCopy; ! this.problemRequestor = problemRequestor; ! } ! protected void executeOperation() throws RubyModelException { ! // open the working copy now to ensure contents are that of the current ! // state of this element ! RubyModelManager.getRubyModelManager().getPerWorkingCopyInfo(workingCopy, true/* ! * create ! * if ! * needed ! */, true/* ! * record ! * usage ! */, problemRequestor); ! workingCopy.openWhenClosed(workingCopy.createElementInfo(), monitor); ! } ! /* ! * @see RubyModelOperation#isReadOnly ! */ ! public boolean isReadOnly() { ! return true; ! } ! /** ! * @param monitor ! * @throws RubyModelException ! */ ! public void runOperation(IProgressMonitor monitor) throws RubyModelException { ! this.monitor = monitor; ! executeOperation(); ! } } --- 20,81 ---- * addition through a delta. */ ! public class BecomeWorkingCopyOperation extends RubyModelOperation { ! private IProblemRequestor problemRequestor; ! /* ! * Creates a BecomeWorkingCopyOperation for the given working copy. ! * perOwnerWorkingCopies map is not null if the working copy is a shared ! * working copy. ! */ ! public BecomeWorkingCopyOperation(RubyScript workingCopy, IProblemRequestor problemRequestor) { ! super(new IRubyElement[] { workingCopy}); ! this.problemRequestor = problemRequestor; ! } ! protected void executeOperation() throws RubyModelException { ! // open the working copy now to ensure contents are that of the current ! // state of this element ! RubyScript workingCopy = getWorkingCopy(); ! RubyModelManager.getRubyModelManager().getPerWorkingCopyInfo(workingCopy, ! true/* create if needed */, true/* record usage */, this.problemRequestor); ! workingCopy.openWhenClosed(workingCopy.createElementInfo(), this.progressMonitor); ! if (!workingCopy.isPrimary()) { ! // report added java delta for a non-primary working copy ! RubyElementDelta delta = new RubyElementDelta(getRubyModel()); ! delta.added(workingCopy); ! addDelta(delta); ! } else { ! if (workingCopy.getResource().isAccessible()) { ! // report a F_PRIMARY_WORKING_COPY change delta for a primary ! // working copy ! RubyElementDelta delta = new RubyElementDelta(getRubyModel()); ! delta.changed(workingCopy, IRubyElementDelta.F_PRIMARY_WORKING_COPY); ! addDelta(delta); ! } else { ! // report an ADDED delta ! RubyElementDelta delta = new RubyElementDelta(this.getRubyModel()); ! delta.added(workingCopy, IRubyElementDelta.F_PRIMARY_WORKING_COPY); ! addDelta(delta); ! } ! } ! this.resultElements = new IRubyElement[] { workingCopy}; ! } ! ! /* ! * Returns the working copy this operation is working on. ! */ ! protected RubyScript getWorkingCopy() { ! return (RubyScript) getElementToProcess(); ! } ! ! /* ! * @see RubyModelOperation#isReadOnly ! */ ! public boolean isReadOnly() { ! return true; ! } } Index: DiscardWorkingCopyOperation.java =================================================================== RCS file: /cvsroot/rubyeclipse/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/DiscardWorkingCopyOperation.java,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** DiscardWorkingCopyOperation.java 2 Mar 2005 00:54:02 -0000 1.2 --- DiscardWorkingCopyOperation.java 22 Feb 2006 20:04:05 -0000 1.3 *************** *** 11,15 **** package org.rubypeople.rdt.internal.core; ! import org.eclipse.core.runtime.IProgressMonitor; import org.rubypeople.rdt.core.RubyModelException; --- 11,16 ---- package org.rubypeople.rdt.internal.core; ! import org.rubypeople.rdt.core.IRubyElement; ! import org.rubypeople.rdt.core.IRubyElementDelta; import org.rubypeople.rdt.core.RubyModelException; *************** *** 18,41 **** * info if the use count is 0) and signal its removal through a delta. */ ! public class DiscardWorkingCopyOperation { ! private RubyScript workingCopy; ! public DiscardWorkingCopyOperation(RubyScript workingCopy) { ! this.workingCopy = workingCopy; ! } ! protected void runOperation(IProgressMonitor monitor) throws RubyModelException { ! int useCount = RubyModelManager.getRubyModelManager().discardPerWorkingCopyInfo(workingCopy); ! if (useCount == 0) { ! // TODO Create RubyElementDeltas ! } ! } ! /** ! * @see RubyModelOperation#isReadOnly ! */ ! public boolean isReadOnly() { ! return true; ! } } --- 19,69 ---- * info if the use count is 0) and signal its removal through a delta. */ ! public class DiscardWorkingCopyOperation extends RubyModelOperation { ! public DiscardWorkingCopyOperation(RubyScript workingCopy) { ! super(new IRubyElement[] { workingCopy}); ! } ! protected void executeOperation() throws RubyModelException { ! RubyScript workingCopy = getWorkingCopy(); ! int useCount = RubyModelManager.getRubyModelManager() ! .discardPerWorkingCopyInfo(workingCopy); ! if (useCount == 0) { ! if (!workingCopy.isPrimary()) { ! // report removed java delta for a non-primary working copy ! RubyElementDelta delta = new RubyElementDelta(this.getRubyModel()); ! delta.removed(workingCopy); ! addDelta(delta); ! removeReconcileDelta(workingCopy); ! } else { ! if (workingCopy.getResource().isAccessible()) { ! // report a F_PRIMARY_WORKING_COPY change delta for a ! // primary working copy ! RubyElementDelta delta = new RubyElementDelta(this.getRubyModel()); ! delta.changed(workingCopy, IRubyElementDelta.F_PRIMARY_WORKING_COPY); ! addDelta(delta); ! } else { ! // report a REMOVED delta ! RubyElementDelta delta = new RubyElementDelta(this.getRubyModel()); ! delta.removed(workingCopy, IRubyElementDelta.F_PRIMARY_WORKING_COPY); ! addDelta(delta); ! } ! } ! } ! } ! /** ! * Returns the working copy this operation is working on. ! */ ! protected RubyScript getWorkingCopy() { ! return (RubyScript) getElementToProcess(); ! } ! ! /** ! * @see RubyModelOperation#isReadOnly ! */ ! public boolean isReadOnly() { ! return true; ! } } |
|
From: Christopher W. <caw...@us...> - 2006-02-22 20:04:09
|
Update of /cvsroot/rubyeclipse/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/util In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv4101/src/org/rubypeople/rdt/internal/core/util Modified Files: Util.java Log Message: extend RubyModelOperation Index: Util.java =================================================================== RCS file: /cvsroot/rubyeclipse/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/util/Util.java,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** Util.java 10 Feb 2006 18:33:18 -0000 1.6 --- Util.java 22 Feb 2006 20:04:04 -0000 1.7 *************** *** 14,17 **** --- 14,18 ---- import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; + import org.rubypeople.rdt.core.IRubyElement; import org.rubypeople.rdt.core.RubyConventions; import org.rubypeople.rdt.core.RubyCore; *************** *** 319,322 **** --- 320,347 ---- } + /* + * Returns whether the given ruby element is exluded from its root's classpath. + * It doesn't check whether the root itself is on the classpath or not + */ + public static final boolean isExcluded(IRubyElement element) { + int elementType = element.getElementType(); + switch (elementType) { + case IRubyElement.RUBY_MODEL: + case IRubyElement.PROJECT: + return false; + case IRubyElement.SCRIPT: + IResource resource = element.getResource(); + if (resource == null) + return false; + // if (isExcluded(resource, root.fullInclusionPatternChars(), root.fullExclusionPatternChars())) + // return true; + return isExcluded(element.getParent()); + + default: + IRubyElement cu = element.getAncestor(IRubyElement.SCRIPT); + return cu != null && isExcluded(cu); + } + } + } |
|
From: Christopher W. <caw...@us...> - 2006-02-22 20:03:51
|
Update of /cvsroot/rubyeclipse/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/formatter In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv3934/src/org/rubypeople/rdt/internal/formatter Modified Files: OldCodeFormatter.java Log Message: Index: OldCodeFormatter.java =================================================================== RCS file: /cvsroot/rubyeclipse/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/formatter/OldCodeFormatter.java,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** OldCodeFormatter.java 18 Feb 2006 16:50:59 -0000 1.2 --- OldCodeFormatter.java 22 Feb 2006 20:03:37 -0000 1.3 *************** *** 366,370 **** } } catch (PatternSyntaxException e) { - // TODO Auto-generated catch block e.printStackTrace(); --- 366,369 ---- |
|
From: Christopher W. <caw...@us...> - 2006-02-18 17:29:39
|
Update of /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv13371/src/org/rubypeople/rdt/internal/ui/text/ruby Modified Files: RubyCodeScanner.java RubyCompletionProcessor.java Log Message: more template work. move RubyTextTools to externally visible package (match JDT) Index: RubyCompletionProcessor.java =================================================================== RCS file: /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/RubyCompletionProcessor.java,v retrieving revision 1.16 retrieving revision 1.17 diff -C2 -d -r1.16 -r1.17 *** RubyCompletionProcessor.java 18 Feb 2006 16:53:51 -0000 1.16 --- RubyCompletionProcessor.java 18 Feb 2006 17:29:33 -0000 1.17 *************** *** 34,42 **** import org.rubypeople.rdt.internal.ui.RubyPlugin; import org.rubypeople.rdt.internal.ui.RubyPluginImages; - import org.rubypeople.rdt.internal.ui.text.RubyTextTools; import org.rubypeople.rdt.internal.ui.text.template.contentassist.RubyTemplateAccess; import org.rubypeople.rdt.internal.ui.text.template.contentassist.TemplateEngine; import org.rubypeople.rdt.internal.ui.text.template.contentassist.TemplateProposal; import org.rubypeople.rdt.ui.IWorkingCopyManager; import org.rubypeople.rdt.ui.text.ruby.IRubyCompletionProposal; --- 34,42 ---- import org.rubypeople.rdt.internal.ui.RubyPlugin; import org.rubypeople.rdt.internal.ui.RubyPluginImages; import org.rubypeople.rdt.internal.ui.text.template.contentassist.RubyTemplateAccess; import org.rubypeople.rdt.internal.ui.text.template.contentassist.TemplateEngine; import org.rubypeople.rdt.internal.ui.text.template.contentassist.TemplateProposal; import org.rubypeople.rdt.ui.IWorkingCopyManager; + import org.rubypeople.rdt.ui.text.RubyTextTools; import org.rubypeople.rdt.ui.text.ruby.IRubyCompletionProposal; Index: RubyCodeScanner.java =================================================================== RCS file: /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/RubyCodeScanner.java,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -d -r1.10 -r1.11 *** RubyCodeScanner.java 27 Jan 2006 16:27:56 -0000 1.10 --- RubyCodeScanner.java 18 Feb 2006 17:29:33 -0000 1.11 *************** *** 10,16 **** import org.eclipse.jface.text.rules.WordRule; import org.rubypeople.rdt.internal.ui.text.IRubyColorConstants; - import org.rubypeople.rdt.internal.ui.text.RubyTextTools; import org.rubypeople.rdt.internal.ui.text.RubyWordDetector; import org.rubypeople.rdt.ui.text.IColorManager; public class RubyCodeScanner extends AbstractRubyScanner { --- 10,16 ---- import org.eclipse.jface.text.rules.WordRule; import org.rubypeople.rdt.internal.ui.text.IRubyColorConstants; import org.rubypeople.rdt.internal.ui.text.RubyWordDetector; import org.rubypeople.rdt.ui.text.IColorManager; + import org.rubypeople.rdt.ui.text.RubyTextTools; public class RubyCodeScanner extends AbstractRubyScanner { |
|
From: Christopher W. <caw...@us...> - 2006-02-18 17:29:39
|
Update of /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/preferences In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv13371/src/org/rubypeople/rdt/internal/ui/preferences Modified Files: RubyTemplatePreferencePage.java Added Files: RubySourcePreviewUpdater.java Log Message: more template work. move RubyTextTools to externally visible package (match JDT) Index: RubyTemplatePreferencePage.java =================================================================== RCS file: /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/preferences/RubyTemplatePreferencePage.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** RubyTemplatePreferencePage.java 18 Feb 2006 16:53:50 -0000 1.1 --- RubyTemplatePreferencePage.java 18 Feb 2006 17:29:33 -0000 1.2 *************** *** 12,31 **** package org.rubypeople.rdt.internal.ui.preferences; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.text.Document; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.source.SourceViewer; - import org.eclipse.jface.text.source.SourceViewerConfiguration; import org.eclipse.jface.text.templates.Template; import org.eclipse.jface.text.templates.persistence.TemplatePersistenceData; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.widgets.Composite; import org.eclipse.ui.texteditor.templates.TemplatePreferencePage; import org.rubypeople.rdt.internal.ui.RubyPlugin; import org.rubypeople.rdt.internal.ui.text.template.contentassist.RubyTemplateAccess; import org.rubypeople.rdt.ui.PreferenceConstants; ! import org.rubypeople.rdt.ui.text.RubySourceViewerConfiguration; /** --- 12,37 ---- package org.rubypeople.rdt.internal.ui.preferences; + import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.text.Document; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.source.SourceViewer; import org.eclipse.jface.text.templates.Template; + import org.eclipse.jface.text.templates.TemplateContextType; import org.eclipse.jface.text.templates.persistence.TemplatePersistenceData; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Font; + import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Composite; + import org.eclipse.swt.widgets.Control; import org.eclipse.ui.texteditor.templates.TemplatePreferencePage; import org.rubypeople.rdt.internal.ui.RubyPlugin; + import org.rubypeople.rdt.internal.ui.rubyeditor.RubySourceViewer; + import org.rubypeople.rdt.internal.ui.text.IRubyPartitions; + import org.rubypeople.rdt.internal.ui.text.SimpleRubySourceViewerConfiguration; import org.rubypeople.rdt.internal.ui.text.template.contentassist.RubyTemplateAccess; import org.rubypeople.rdt.ui.PreferenceConstants; ! import org.rubypeople.rdt.ui.text.RubyTextTools; /** *************** *** 56,73 **** * @see org.eclipse.ui.texteditor.templates.TemplatePreferencePage#createViewer(org.eclipse.swt.widgets.Composite) */ ! protected SourceViewer createViewer(Composite parent) { ! SourceViewer viewer = new SourceViewer(parent, null, null, false, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL); ! ! // FIXME Pass in the current editor! ! SourceViewerConfiguration configuration = new RubySourceViewerConfiguration(RubyPlugin.getDefault().getRubyTextTools(), null); ! IDocument document = new Document(); ! // FIXME Do we need this? ! //new AntDocumentSetupParticipant().setup(document); viewer.configure(configuration); - viewer.setDocument(document); viewer.setEditable(false); ! Font font = JFaceResources.getFont(JFaceResources.TEXT_FONT); viewer.getTextWidget().setFont(font); ! return viewer; } --- 62,84 ---- * @see org.eclipse.ui.texteditor.templates.TemplatePreferencePage#createViewer(org.eclipse.swt.widgets.Composite) */ ! protected SourceViewer createViewer(Composite parent) { ! IDocument document= new Document(); ! RubyTextTools tools= RubyPlugin.getDefault().getRubyTextTools(); ! tools.setupRubyDocumentPartitioner(document, IRubyPartitions.RUBY_PARTITIONING); ! IPreferenceStore store= RubyPlugin.getDefault().getCombinedPreferenceStore(); ! SourceViewer viewer= new RubySourceViewer(parent, null, null, false, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL, store); ! SimpleRubySourceViewerConfiguration configuration= new SimpleRubySourceViewerConfiguration(tools.getColorManager(), store, null, IRubyPartitions.RUBY_PARTITIONING, false); viewer.configure(configuration); viewer.setEditable(false); ! viewer.setDocument(document); ! ! Font font= JFaceResources.getFont(PreferenceConstants.EDITOR_TEXT_FONT); viewer.getTextWidget().setFont(font); ! new RubySourcePreviewerUpdater(viewer, configuration, store); ! ! Control control= viewer.getControl(); ! GridData data= new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.FILL_VERTICAL); ! control.setLayoutData(data); ! return viewer; } *************** *** 86,104 **** */ protected void updateViewerInput() { ! IStructuredSelection selection = (IStructuredSelection) getTableViewer().getSelection(); ! SourceViewer viewer = getViewer(); ! if (selection.size() == 1 && selection.getFirstElement() instanceof TemplatePersistenceData) { ! TemplatePersistenceData data = (TemplatePersistenceData) selection.getFirstElement(); ! Template template = data.getTemplate(); ! if (RubyPlugin.getDefault().getPreferenceStore().getBoolean(getFormatterPreferenceKey())) { ! String formatted = RubyPlugin.getDefault().getCodeFormatter().formatString(template.getPattern()); ! viewer.getDocument().set(formatted); ! } else { ! viewer.getDocument().set(template.getPattern()); ! } } else { viewer.getDocument().set(""); //$NON-NLS-1$ ! } } --- 97,123 ---- */ protected void updateViewerInput() { ! IStructuredSelection selection= (IStructuredSelection) getTableViewer().getSelection(); ! SourceViewer viewer= getViewer(); ! if (selection.size() == 1 && selection.getFirstElement() instanceof TemplatePersistenceData) { ! TemplatePersistenceData data= (TemplatePersistenceData) selection.getFirstElement(); ! Template template= data.getTemplate(); ! String contextId= template.getContextTypeId(); ! ! IDocument doc= viewer.getDocument(); ! ! String start= null; ! if ("rdoc".equals(contextId)) { //$NON-NLS-1$ ! start= "/**" + doc.getLegalLineDelimiters()[0]; //$NON-NLS-1$ ! } else ! start= ""; //$NON-NLS-1$ ! ! doc.set(start + template.getPattern()); ! int startLen= start.length(); ! viewer.setDocument(doc, startLen, doc.getLength() - startLen); ! } else { viewer.getDocument().set(""); //$NON-NLS-1$ ! } } --- NEW FILE: RubySourcePreviewUpdater.java --- /******************************************************************************* * Copyright (c) 2000, 2005 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.rubypeople.rdt.internal.ui.preferences; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.text.source.SourceViewer; import org.eclipse.jface.util.Assert; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.graphics.Font; import org.rubypeople.rdt.ui.PreferenceConstants; import org.rubypeople.rdt.ui.text.RubySourceViewerConfiguration; /** * Handles Ruby editor font changes for Ruby source preview viewers. * * @since 3.0 */ class RubySourcePreviewerUpdater { /** * Creates a Ruby source preview updater for the given viewer, configuration and preference store. * * @param viewer the viewer * @param configuration the configuration * @param preferenceStore the preference store */ RubySourcePreviewerUpdater(final SourceViewer viewer, final RubySourceViewerConfiguration configuration, final IPreferenceStore preferenceStore) { Assert.isNotNull(viewer); Assert.isNotNull(configuration); Assert.isNotNull(preferenceStore); final IPropertyChangeListener fontChangeListener= new IPropertyChangeListener() { /* * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent) */ public void propertyChange(PropertyChangeEvent event) { if (event.getProperty().equals(PreferenceConstants.EDITOR_TEXT_FONT)) { Font font= JFaceResources.getFont(PreferenceConstants.EDITOR_TEXT_FONT); viewer.getTextWidget().setFont(font); } } }; final IPropertyChangeListener propertyChangeListener= new IPropertyChangeListener() { /* * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent) */ public void propertyChange(PropertyChangeEvent event) { if (configuration.affectsTextPresentation(event)) { configuration.handlePropertyChangeEvent(event); viewer.invalidateTextPresentation(); } } }; viewer.getTextWidget().addDisposeListener(new DisposeListener() { /* * @see org.eclipse.swt.events.DisposeListener#widgetDisposed(org.eclipse.swt.events.DisposeEvent) */ public void widgetDisposed(DisposeEvent e) { preferenceStore.removePropertyChangeListener(propertyChangeListener); JFaceResources.getFontRegistry().removeListener(fontChangeListener); } }); JFaceResources.getFontRegistry().addListener(fontChangeListener); preferenceStore.addPropertyChangeListener(propertyChangeListener); } } |
|
From: Christopher W. <caw...@us...> - 2006-02-18 17:29:39
|
Update of /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/text In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv13371/src/org/rubypeople/rdt/ui/text Modified Files: RubySourceViewerConfiguration.java Added Files: RubyTextTools.java Log Message: more template work. move RubyTextTools to externally visible package (match JDT) --- NEW FILE: RubyTextTools.java --- package org.rubypeople.rdt.ui.text; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; import org.eclipse.core.runtime.Preferences; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IDocumentExtension3; import org.eclipse.jface.text.IDocumentPartitioner; import org.eclipse.jface.text.rules.DefaultPartitioner; import org.eclipse.jface.text.rules.IPartitionTokenScanner; import org.eclipse.jface.text.rules.ITokenScanner; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.rubypeople.rdt.internal.ui.RubyPlugin; import org.rubypeople.rdt.internal.ui.rubyeditor.RubyEditorPreferences; import org.rubypeople.rdt.internal.ui.text.IRubyColorConstants; import org.rubypeople.rdt.internal.ui.text.RubyColorManager; import org.rubypeople.rdt.internal.ui.text.RubyCommentScanner; import org.rubypeople.rdt.internal.ui.text.RubyPartitionScanner; import org.rubypeople.rdt.internal.ui.text.ruby.AbstractRubyScanner; import org.rubypeople.rdt.internal.ui.text.ruby.RubyCodeScanner; import org.rubypeople.rdt.internal.ui.text.ruby.SingleTokenRubyCodeScanner; public class RubyTextTools { /** * This tools' preference listener. */ private class PreferenceListener implements IPropertyChangeListener, Preferences.IPropertyChangeListener { public void propertyChange(PropertyChangeEvent event) { adaptToPreferenceChange(event); } public void propertyChange(Preferences.PropertyChangeEvent event) { adaptToPreferenceChange(new PropertyChangeEvent(event.getSource(), event.getProperty(), event.getOldValue(), event.getNewValue())); } } protected static String[] keywords; protected RubyColorManager fColorManager; protected RubyPartitionScanner partitionScanner; protected AbstractRubyScanner fCodeScanner; protected AbstractRubyScanner fMultilineCommentScanner, fSinglelineCommentScanner, stringScanner; private IPreferenceStore fPreferenceStore; private Preferences fCorePreferenceStore; /** The preference change listener */ private PreferenceListener fPreferenceListener = new PreferenceListener(); private SingleTokenRubyCodeScanner fRegexpScanner; private SingleTokenRubyCodeScanner fCommandScanner; /** * Creates a new Ruby text tools collection. * * @param store * the preference store to initialize the text tools. The text * tool instance installs a listener on the passed preference * store to adapt itself to changes in the preference store. In * general <code>PreferenceConstants. * getPreferenceStore()</code> * should be used to initialize the text tools. * @param coreStore * optional preference store to initialize the text tools. The * text tool instance installs a listener on the passed * preference store to adapt itself to changes in the preference * store. * @see org.rubypeople.rdt.ui.PreferenceConstants#getPreferenceStore() * @since 2.1 */ public RubyTextTools(IPreferenceStore store, Preferences coreStore) { this(store, coreStore, true); } /** * Creates a new Ruby text tools collection. * * @param store * the preference store to initialize the text tools. The text * tool instance installs a listener on the passed preference * store to adapt itself to changes in the preference store. In * general <code>PreferenceConstants. * getPreferenceStore()</code> * should be used to initialize the text tools. * @param coreStore * optional preference store to initialize the text tools. The * text tool instance installs a listener on the passed * preference store to adapt itself to changes in the preference * store. * @param autoDisposeOnDisplayDispose * if <code>true</code> the color manager automatically * disposes all managed colors when the current display gets * disposed and all calls to * {@link org.eclipse.jface.text.source.ISharedTextColors#dispose()} * are ignored. * @see org.rubypeople.rdt.ui.PreferenceConstants#getPreferenceStore() * @since 2.1 */ public RubyTextTools(IPreferenceStore store, Preferences coreStore, boolean autoDisposeOnDisplayDispose) { super(); fColorManager = new RubyColorManager(autoDisposeOnDisplayDispose); partitionScanner = new RubyPartitionScanner(); fCodeScanner = new RubyCodeScanner(fColorManager, store); fMultilineCommentScanner = new RubyCommentScanner(fColorManager, store, coreStore, IRubyColorConstants.RUBY_MULTI_LINE_COMMENT); fSinglelineCommentScanner = new RubyCommentScanner(fColorManager, store, coreStore, IRubyColorConstants.RUBY_SINGLE_LINE_COMMENT); stringScanner = new SingleTokenRubyCodeScanner(fColorManager, store, IRubyColorConstants.RUBY_STRING); fRegexpScanner = new SingleTokenRubyCodeScanner(fColorManager, store, IRubyColorConstants.RUBY_REGEXP); fCommandScanner = new SingleTokenRubyCodeScanner(fColorManager, store, IRubyColorConstants.RUBY_COMMAND); fPreferenceStore = store; fPreferenceStore.addPropertyChangeListener(fPreferenceListener); fCorePreferenceStore = coreStore; if (fCorePreferenceStore != null) fCorePreferenceStore.addPropertyChangeListener(fPreferenceListener); // fJavaDocScanner= new JavaDocScanner(fColorManager, store, coreStore); // fPartitionScanner= new FastJavaPartitionScanner(); } /** * Adapts the behavior of the contained components to the change encoded in * the given event. * * @param event * the event to which to adapt * @since 2.0 * @deprecated As of 3.0, no replacement */ protected void adaptToPreferenceChange(PropertyChangeEvent event) { if (fCodeScanner.affectsBehavior(event)) fCodeScanner.adaptToPreferenceChange(event); if (fMultilineCommentScanner.affectsBehavior(event)) fMultilineCommentScanner.adaptToPreferenceChange(event); if (fSinglelineCommentScanner.affectsBehavior(event)) fSinglelineCommentScanner.adaptToPreferenceChange(event); if (stringScanner.affectsBehavior(event)) stringScanner.adaptToPreferenceChange(event); if (fRegexpScanner.affectsBehavior(event)) fRegexpScanner.adaptToPreferenceChange(event); if (fCommandScanner.affectsBehavior(event)) fCommandScanner.adaptToPreferenceChange(event); // if (fJavaDocScanner.affectsBehavior(event)) // fJavaDocScanner.adaptToPreferenceChange(event); } public IDocumentPartitioner createDocumentPartitioner() { return new DefaultPartitioner(getPartitionScanner(), RubyPartitionScanner.LEGAL_CONTENT_TYPES); } protected IPartitionTokenScanner getPartitionScanner() { return partitionScanner; } /** * @deprecated As of 0.8.0, replaced by * {@link RubySourceViewerConfiguration#getCodeScanner()} */ public AbstractRubyScanner getCodeScanner() { return fCodeScanner; } /** * @deprecated As of 0.8.0, replaced by * {@link RubySourceViewerConfiguration#getMultilineCommentScanner()} */ public ITokenScanner getMultilineCommentScanner() { return fMultilineCommentScanner; } /** * @deprecated As of 0.8.0, replaced by * {@link RubySourceViewerConfiguration#getSingleineCommentScanner()} */ public ITokenScanner getSinglelineCommentScanner() { return fSinglelineCommentScanner; } /** * @deprecated As of 0.8.0, replaced by * {@link RubySourceViewerConfiguration#getStringScanner()} */ public ITokenScanner getStringScanner() { return stringScanner; } public IPreferenceStore getPreferenceStore() { return RubyPlugin.getDefault().getPreferenceStore(); } public static String[] getKeyWords() { if (keywords == null) { String csvKeywords = RubyEditorPreferences.getString("keywords"); List keywordList = new ArrayList(); StringTokenizer tokenizer = new StringTokenizer(csvKeywords, ","); while (tokenizer.hasMoreTokens()) keywordList.add(tokenizer.nextToken()); keywords = new String[keywordList.size()]; keywordList.toArray(keywords); } return keywords; } public boolean affectsTextPresentation(PropertyChangeEvent event) { return fCodeScanner.affectsBehavior(event) || fMultilineCommentScanner.affectsBehavior(event) || fSinglelineCommentScanner.affectsBehavior(event) || stringScanner.affectsBehavior(event) || fRegexpScanner.affectsBehavior(event) || fCommandScanner.affectsBehavior(event); } /** * Sets up the Ruby document partitioner for the given document for the * given partitioning. * * @param document * the document to be set up * @param partitioning * the document partitioning * @since 3.0 */ public void setupRubyDocumentPartitioner(IDocument document, String partitioning) { IDocumentPartitioner partitioner = createDocumentPartitioner(); if (document instanceof IDocumentExtension3) { IDocumentExtension3 extension3 = (IDocumentExtension3) document; extension3.setDocumentPartitioner(partitioning, partitioner); } else { document.setDocumentPartitioner(partitioner); } partitioner.connect(document); } /** * Disposes all the individual tools of this tools collection. */ public void dispose() { fCodeScanner = null; fMultilineCommentScanner = null; fSinglelineCommentScanner = null; stringScanner = null; fRegexpScanner = null; fCommandScanner = null; // fJavaDocScanner= null; partitionScanner = null; if (fColorManager != null) { fColorManager.dispose(); fColorManager = null; } if (fPreferenceStore != null) { fPreferenceStore.removePropertyChangeListener(fPreferenceListener); fPreferenceStore = null; if (fCorePreferenceStore != null) { fCorePreferenceStore.removePropertyChangeListener(fPreferenceListener); fCorePreferenceStore = null; } fPreferenceListener = null; } } /** * @deprecated As of 0.8.0, replaced by * {@link RubySourceViewerConfiguration#getRegexpScanner()} */ public ITokenScanner getRegexpScanner() { return fRegexpScanner; } /** * @deprecated As of 0.8.0, replaced by * {@link RubySourceViewerConfiguration#getCommandScanner()} */ public ITokenScanner getCommandScanner() { return fCommandScanner; } /** * Returns the color manager which is used to manage any Ruby-specific * colors needed for such things like syntax highlighting. * <p> * Clients which are only interested in the color manager of the Ruby UI * plug-in should use {@link org.rubypeople.rdt.ui.RubyUI#getColorManager()}. * </p> * * @return the color manager to be used for Ruby text viewers * @see org.rubypeople.rdt.ui.RubyUI#getColorManager() */ public IColorManager getColorManager() { return fColorManager; } /** * Returns this text tool's core preference store. * * @return the core preference store * @since 0.8.0 */ public Preferences getCorePreferenceStore() { return fCorePreferenceStore; } /** * Sets up the Ruby document partitioner for the given document for the * default partitioning. * * @param document * the document to be set up * @since 0.8.0 */ public void setupRubyDocumentPartitioner(IDocument document) { setupRubyDocumentPartitioner(document, IDocumentExtension3.DEFAULT_PARTITIONING); } } Index: RubySourceViewerConfiguration.java =================================================================== RCS file: /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/text/RubySourceViewerConfiguration.java,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** RubySourceViewerConfiguration.java 10 Feb 2006 23:05:47 -0000 1.2 --- RubySourceViewerConfiguration.java 18 Feb 2006 17:29:33 -0000 1.3 *************** *** 42,46 **** import org.rubypeople.rdt.internal.ui.text.RubyPartitionScanner; import org.rubypeople.rdt.internal.ui.text.RubyReconciler; - import org.rubypeople.rdt.internal.ui.text.RubyTextTools; import org.rubypeople.rdt.internal.ui.text.comment.CommentFormattingStrategy; import org.rubypeople.rdt.internal.ui.text.ruby.AbstractRubyScanner; --- 42,45 ---- |
|
From: Christopher W. <caw...@us...> - 2006-02-18 17:29:39
|
Update of /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv13371/src/org/rubypeople/rdt/internal/ui Modified Files: RubyPlugin.java Log Message: more template work. move RubyTextTools to externally visible package (match JDT) Index: RubyPlugin.java =================================================================== RCS file: /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/RubyPlugin.java,v retrieving revision 1.24 retrieving revision 1.25 diff -C2 -d -r1.24 -r1.25 *** RubyPlugin.java 18 Feb 2006 16:53:50 -0000 1.24 --- RubyPlugin.java 18 Feb 2006 17:29:34 -0000 1.25 *************** *** 58,66 **** import org.rubypeople.rdt.internal.ui.text.IRubyColorConstants; import org.rubypeople.rdt.internal.ui.text.PreferencesAdapter; - import org.rubypeople.rdt.internal.ui.text.RubyTextTools; import org.rubypeople.rdt.internal.ui.text.folding.RubyFoldingStructureProviderRegistry; import org.rubypeople.rdt.internal.ui.text.template.contentassist.RubyTemplateAccess; import org.rubypeople.rdt.ui.IWorkingCopyManager; import org.rubypeople.rdt.ui.PreferenceConstants; public class RubyPlugin extends AbstractUIPlugin implements IRubyColorConstants { --- 58,66 ---- import org.rubypeople.rdt.internal.ui.text.IRubyColorConstants; import org.rubypeople.rdt.internal.ui.text.PreferencesAdapter; import org.rubypeople.rdt.internal.ui.text.folding.RubyFoldingStructureProviderRegistry; import org.rubypeople.rdt.internal.ui.text.template.contentassist.RubyTemplateAccess; import org.rubypeople.rdt.ui.IWorkingCopyManager; import org.rubypeople.rdt.ui.PreferenceConstants; + import org.rubypeople.rdt.ui.text.RubyTextTools; public class RubyPlugin extends AbstractUIPlugin implements IRubyColorConstants { |
|
From: Christopher W. <caw...@us...> - 2006-02-18 17:29:39
|
Update of /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv13371/src/org/rubypeople/rdt/internal/ui/text Removed Files: RubyTextTools.java Log Message: more template work. move RubyTextTools to externally visible package (match JDT) --- RubyTextTools.java DELETED --- |
|
From: Christopher W. <caw...@us...> - 2006-02-18 17:29:38
|
Update of /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/preferences/formatter In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv13371/src/org/rubypeople/rdt/internal/ui/preferences/formatter Modified Files: RubyPreview.java Log Message: more template work. move RubyTextTools to externally visible package (match JDT) Index: RubyPreview.java =================================================================== RCS file: /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/preferences/formatter/RubyPreview.java,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** RubyPreview.java 10 Feb 2006 23:05:47 -0000 1.2 --- RubyPreview.java 18 Feb 2006 17:29:33 -0000 1.3 *************** *** 35,41 **** import org.rubypeople.rdt.internal.ui.rubyeditor.RubySourceViewer; import org.rubypeople.rdt.internal.ui.text.IRubyPartitions; - import org.rubypeople.rdt.internal.ui.text.RubyTextTools; import org.rubypeople.rdt.internal.ui.text.SimpleRubySourceViewerConfiguration; import org.rubypeople.rdt.ui.PreferenceConstants; public abstract class RubyPreview { --- 35,41 ---- import org.rubypeople.rdt.internal.ui.rubyeditor.RubySourceViewer; import org.rubypeople.rdt.internal.ui.text.IRubyPartitions; import org.rubypeople.rdt.internal.ui.text.SimpleRubySourceViewerConfiguration; import org.rubypeople.rdt.ui.PreferenceConstants; + import org.rubypeople.rdt.ui.text.RubyTextTools; public abstract class RubyPreview { |
|
From: Christopher W. <caw...@us...> - 2006-02-18 17:29:37
|
Update of /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv13371/src/org/rubypeople/rdt/internal/ui/rubyeditor Modified Files: ExternalRubyDocumentProvider.java RubyAbstractEditor.java RubyDocumentSetupParticipant.java Log Message: more template work. move RubyTextTools to externally visible package (match JDT) Index: RubyDocumentSetupParticipant.java =================================================================== RCS file: /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyDocumentSetupParticipant.java,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** RubyDocumentSetupParticipant.java 10 Feb 2006 20:14:31 -0000 1.3 --- RubyDocumentSetupParticipant.java 18 Feb 2006 17:29:33 -0000 1.4 *************** *** 15,19 **** import org.rubypeople.rdt.internal.ui.RubyPlugin; import org.rubypeople.rdt.internal.ui.text.IRubyPartitions; ! import org.rubypeople.rdt.internal.ui.text.RubyTextTools; /** --- 15,19 ---- import org.rubypeople.rdt.internal.ui.RubyPlugin; import org.rubypeople.rdt.internal.ui.text.IRubyPartitions; ! import org.rubypeople.rdt.ui.text.RubyTextTools; /** Index: ExternalRubyDocumentProvider.java =================================================================== RCS file: /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/ExternalRubyDocumentProvider.java,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** ExternalRubyDocumentProvider.java 10 Feb 2006 20:14:31 -0000 1.5 --- ExternalRubyDocumentProvider.java 18 Feb 2006 17:29:33 -0000 1.6 *************** *** 16,20 **** import org.rubypeople.rdt.internal.ui.RubyUIMessages; import org.rubypeople.rdt.internal.ui.RubyPlugin; ! import org.rubypeople.rdt.internal.ui.text.RubyTextTools; public class ExternalRubyDocumentProvider extends AbstractDocumentProvider { --- 16,20 ---- import org.rubypeople.rdt.internal.ui.RubyUIMessages; import org.rubypeople.rdt.internal.ui.RubyPlugin; ! import org.rubypeople.rdt.ui.text.RubyTextTools; public class ExternalRubyDocumentProvider extends AbstractDocumentProvider { Index: RubyAbstractEditor.java =================================================================== RCS file: /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyAbstractEditor.java,v retrieving revision 1.22 retrieving revision 1.23 diff -C2 -d -r1.22 -r1.23 *** RubyAbstractEditor.java 10 Feb 2006 20:14:31 -0000 1.22 --- RubyAbstractEditor.java 18 Feb 2006 17:29:33 -0000 1.23 *************** *** 32,38 **** import org.rubypeople.rdt.core.RubyModelException; import org.rubypeople.rdt.internal.ui.RubyPlugin; - import org.rubypeople.rdt.internal.ui.text.RubyTextTools; import org.rubypeople.rdt.ui.IWorkingCopyManager; import org.rubypeople.rdt.ui.text.RubySourceViewerConfiguration; public abstract class RubyAbstractEditor extends TextEditor { --- 32,38 ---- import org.rubypeople.rdt.core.RubyModelException; import org.rubypeople.rdt.internal.ui.RubyPlugin; import org.rubypeople.rdt.ui.IWorkingCopyManager; import org.rubypeople.rdt.ui.text.RubySourceViewerConfiguration; + import org.rubypeople.rdt.ui.text.RubyTextTools; public abstract class RubyAbstractEditor extends TextEditor { |
|
From: Christopher W. <caw...@us...> - 2006-02-18 17:28:59
|
Update of /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/rubyeditor In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12916/src/org/rubypeople/rdt/ui/rubyeditor Modified Files: RubyEditorPreferences.properties Log Message: oops missed a couple keywords Index: RubyEditorPreferences.properties =================================================================== RCS file: /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/rubyeditor/RubyEditorPreferences.properties,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** RubyEditorPreferences.properties 18 Feb 2006 17:17:48 -0000 1.5 --- RubyEditorPreferences.properties 18 Feb 2006 17:28:55 -0000 1.6 *************** *** 1 **** ! keywords=BEGIN,END,alias,begin,do,end,yield,if,unless,elsif,else,while,unless,for,in,super,retry,redo,break,case,when,throw,and,or,not,raise,rescue,ensure,new,each \ No newline at end of file --- 1 ---- ! keywords=BEGIN,END,alias,begin,do,end,yield,if,unless,elsif,else,while,unless,for,in,super,retry,redo,break,case,when,throw,and,or,not,raise,rescue,ensure,new,each,def,class,module,return \ No newline at end of file |
|
From: Christopher W. <caw...@us...> - 2006-02-18 17:17:55
|
Update of /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/rubyeditor In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv8048/src/org/rubypeople/rdt/ui/rubyeditor Modified Files: RubyEditorPreferences.properties Log Message: only list actual ruby keywords as keywords. We're highlighting common kernel methods as keywords right now, and it can be confusing. Index: RubyEditorPreferences.properties =================================================================== RCS file: /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/rubyeditor/RubyEditorPreferences.properties,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** RubyEditorPreferences.properties 4 Mar 2004 01:21:14 -0000 1.4 --- RubyEditorPreferences.properties 18 Feb 2006 17:17:48 -0000 1.5 *************** *** 1 **** ! keywords=alias,and,begin,break,case,class,def,defined?,do,else,elsif,end,ensure,false,for,if,in,module,next,nil,not,or,private,protected,public,puts,raise,redo,require,rescue,retry,return,self,super,then,throw,true,undef,unless,until,when,while,yield,?BEGIN,?END,__FILE__,__LINE__ \ No newline at end of file --- 1 ---- ! keywords=BEGIN,END,alias,begin,do,end,yield,if,unless,elsif,else,while,unless,for,in,super,retry,redo,break,case,when,throw,and,or,not,raise,rescue,ensure,new,each \ No newline at end of file |
|
From: Christopher W. <caw...@us...> - 2006-02-18 16:53:56
|
Update of /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/hover In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv28822/src/org/rubypeople/rdt/internal/ui/text/ruby/hover Added Files: SourceViewerInformationControl.java Log Message: overhaul our completion proposal/template code. Now we will apply formatting to templates when inserted! Plus we're closer to the way JDT does things. We still can't use the actual code formatter on the templates (because our old one does a massive replace edit which messes up variables like the cursor placement). The end result is that users should create templates with somewhat proper formatting initially. --- NEW FILE: SourceViewerInformationControl.java --- /******************************************************************************* * Copyright (c) 2000, 2005 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.rubypeople.rdt.internal.ui.text.ruby.hover; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.text.Document; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IInformationControl; import org.eclipse.jface.text.IInformationControlExtension; import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.jface.text.source.SourceViewer; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.events.FocusListener; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.KeyListener; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.FontData; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.rubypeople.rdt.internal.ui.RubyPlugin; import org.rubypeople.rdt.internal.ui.rubyeditor.RubySourceViewer; import org.rubypeople.rdt.internal.ui.text.SimpleRubySourceViewerConfiguration; /** * Source viewer based implementation of <code>IInformationControl</code>. * Displays information in a source viewer. * * @since 3.0 */ public class SourceViewerInformationControl implements IInformationControl, IInformationControlExtension, DisposeListener { /** Border thickness in pixels. */ private static final int BORDER= 1; /** The control's shell */ private Shell fShell; /** The control's text widget */ private StyledText fText; /** The control's source viewer */ private SourceViewer fViewer; /** * The optional status field. * * @since 3.0 */ private Label fStatusField; /** * The separator for the optional status field. * * @since 3.0 */ private Label fSeparator; /** * The font of the optional status text label. * * @since 3.0 */ private Font fStatusTextFont; /** * Creates a default information control with the given shell as parent. The given * information presenter is used to process the information to be displayed. The given * styles are applied to the created styled text widget. * * @param parent the parent shell * @param shellStyle the additional styles for the shell * @param style the additional styles for the styled text widget */ public SourceViewerInformationControl(Shell parent, int shellStyle, int style) { this(parent, shellStyle, style, null); } /** * Creates a default information control with the given shell as parent. The given * information presenter is used to process the information to be displayed. The given * styles are applied to the created styled text widget. * * @param parent the parent shell * @param shellStyle the additional styles for the shell * @param style the additional styles for the styled text widget * @param statusFieldText the text to be used in the optional status field * or <code>null</code> if the status field should be hidden * @since 3.0 */ public SourceViewerInformationControl(Shell parent, int shellStyle, int style, String statusFieldText) { GridLayout layout; GridData gd; fShell= new Shell(parent, SWT.NO_FOCUS | SWT.ON_TOP | shellStyle); Display display= fShell.getDisplay(); fShell.setBackground(display.getSystemColor(SWT.COLOR_BLACK)); Composite composite= fShell; layout= new GridLayout(1, false); int border= ((shellStyle & SWT.NO_TRIM) == 0) ? 0 : BORDER; layout.marginHeight= border; layout.marginWidth= border; composite.setLayout(layout); gd= new GridData(GridData.FILL_HORIZONTAL); composite.setLayoutData(gd); if (statusFieldText != null) { composite= new Composite(composite, SWT.NONE); layout= new GridLayout(1, false); layout.marginHeight= 0; layout.marginWidth= 0; composite.setLayout(layout); gd= new GridData(GridData.FILL_BOTH); composite.setLayoutData(gd); composite.setForeground(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND)); composite.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND)); } // Source viewer IPreferenceStore store= RubyPlugin.getDefault().getCombinedPreferenceStore(); fViewer= new RubySourceViewer(composite, null, null, false, style, store); fViewer.configure(new SimpleRubySourceViewerConfiguration(RubyPlugin.getDefault().getRubyTextTools().getColorManager(), store, null, null, false)); fViewer.setEditable(false); fText= fViewer.getTextWidget(); gd= new GridData(GridData.BEGINNING | GridData.FILL_BOTH); fText.setLayoutData(gd); fText.setForeground(parent.getDisplay().getSystemColor(SWT.COLOR_INFO_FOREGROUND)); fText.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND)); fText.addKeyListener(new KeyListener() { public void keyPressed(KeyEvent e) { if (e.character == 0x1B) // ESC fShell.dispose(); } public void keyReleased(KeyEvent e) {} }); // Status field if (statusFieldText != null) { // Horizontal separator line fSeparator= new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL | SWT.LINE_DOT); fSeparator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); // Status field label fStatusField= new Label(composite, SWT.RIGHT); fStatusField.setText(statusFieldText); Font font= fStatusField.getFont(); FontData[] fontDatas= font.getFontData(); for (int i= 0; i < fontDatas.length; i++) fontDatas[i].setHeight(fontDatas[i].getHeight() * 9 / 10); fStatusTextFont= new Font(fStatusField.getDisplay(), fontDatas); fStatusField.setFont(fStatusTextFont); GridData gd2= new GridData(GridData.FILL_VERTICAL | GridData.FILL_HORIZONTAL | GridData.HORIZONTAL_ALIGN_BEGINNING | GridData.VERTICAL_ALIGN_BEGINNING); fStatusField.setLayoutData(gd2); // Regarding the color see bug 41128 fStatusField.setForeground(display.getSystemColor(SWT.COLOR_WIDGET_DARK_SHADOW)); fStatusField.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND)); } addDisposeListener(this); } /** * Creates a default information control with the given shell as parent. The given * information presenter is used to process the information to be displayed. The given * styles are applied to the created styled text widget. * * @param parent the parent shell * @param style the additional styles for the styled text widget */ public SourceViewerInformationControl(Shell parent,int style) { this(parent, SWT.NO_TRIM | SWT.TOOL, style); } /** * Creates a default information control with the given shell as parent. The given * information presenter is used to process the information to be displayed. The given * styles are applied to the created styled text widget. * * @param parent the parent shell * @param style the additional styles for the styled text widget * @param statusFieldText the text to be used in the optional status field * or <code>null</code> if the status field should be hidden * @since 3.0 */ public SourceViewerInformationControl(Shell parent,int style, String statusFieldText) { this(parent, SWT.NO_TRIM | SWT.TOOL, style, statusFieldText); } /** * Creates a default information control with the given shell as parent. * No information presenter is used to process the information * to be displayed. No additional styles are applied to the styled text widget. * * @param parent the parent shell */ public SourceViewerInformationControl(Shell parent) { this(parent, SWT.NONE); } /** * Creates a default information control with the given shell as parent. * No information presenter is used to process the information * to be displayed. No additional styles are applied to the styled text widget. * * @param parent the parent shell * @param statusFieldText the text to be used in the optional status field * or <code>null</code> if the status field should be hidden * @since 3.0 */ public SourceViewerInformationControl(Shell parent, String statusFieldText) { this(parent, SWT.NONE, statusFieldText); } /* * @see org.eclipse.jface.text.IInformationControlExtension2#setInput(java.lang.Object) */ public void setInput(Object input) { if (input instanceof String) setInformation((String)input); else setInformation(null); } /* * @see IInformationControl#setInformation(String) */ public void setInformation(String content) { if (content == null) { fViewer.setInput(null); return; } IDocument doc= new Document(content); RubyPlugin.getDefault().getRubyTextTools().setupRubyDocumentPartitioner(doc); fViewer.setInput(doc); } /* * @see IInformationControl#setVisible(boolean) */ public void setVisible(boolean visible) { fShell.setVisible(visible); } /** * {@inheritDoc} * @since 3.0 */ public void widgetDisposed(DisposeEvent event) { if (fStatusTextFont != null && !fStatusTextFont.isDisposed()) fStatusTextFont.dispose(); fStatusTextFont= null; fShell= null; fText= null; } /** * {@inheritDoc} */ public final void dispose() { if (fShell != null && !fShell.isDisposed()) fShell.dispose(); else widgetDisposed(null); } /* * @see IInformationControl#setSize(int, int) */ public void setSize(int width, int height) { if (fStatusField != null) { GridData gd= (GridData)fViewer.getTextWidget().getLayoutData(); Point statusSize= fStatusField.computeSize(SWT.DEFAULT, SWT.DEFAULT, true); Point separatorSize= fSeparator.computeSize(SWT.DEFAULT, SWT.DEFAULT, true); gd.heightHint= height - statusSize.y - separatorSize.y; } fShell.setSize(width, height); if (fStatusField != null) fShell.pack(true); } /* * @see IInformationControl#setLocation(Point) */ public void setLocation(Point location) { Rectangle trim= fShell.computeTrim(0, 0, 0, 0); Point textLocation= fText.getLocation(); location.x += trim.x - textLocation.x; location.y += trim.y - textLocation.y; fShell.setLocation(location); } /* * @see IInformationControl#setSizeConstraints(int, int) */ public void setSizeConstraints(int maxWidth, int maxHeight) { maxWidth= maxHeight; } /* * @see IInformationControl#computeSizeHint() */ public Point computeSizeHint() { return fShell.computeSize(SWT.DEFAULT, SWT.DEFAULT); } /* * @see IInformationControl#addDisposeListener(DisposeListener) */ public void addDisposeListener(DisposeListener listener) { fShell.addDisposeListener(listener); } /* * @see IInformationControl#removeDisposeListener(DisposeListener) */ public void removeDisposeListener(DisposeListener listener) { fShell.removeDisposeListener(listener); } /* * @see IInformationControl#setForegroundColor(Color) */ public void setForegroundColor(Color foreground) { fText.setForeground(foreground); } /* * @see IInformationControl#setBackgroundColor(Color) */ public void setBackgroundColor(Color background) { fText.setBackground(background); } /* * @see IInformationControl#isFocusControl() */ public boolean isFocusControl() { return fText.isFocusControl(); } /* * @see IInformationControl#setFocus() */ public void setFocus() { fShell.forceFocus(); fText.setFocus(); } /* * @see IInformationControl#addFocusListener(FocusListener) */ public void addFocusListener(FocusListener listener) { fText.addFocusListener(listener); } /* * @see IInformationControl#removeFocusListener(FocusListener) */ public void removeFocusListener(FocusListener listener) { fText.removeFocusListener(listener); } /* * @see IInformationControlExtension#hasContents() */ public boolean hasContents() { return fText.getCharCount() > 0; } protected ISourceViewer getViewer() { return fViewer; } } |
|
From: Christopher W. <caw...@us...> - 2006-02-18 16:53:56
|
Update of /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/preferences In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv28822/src/org/rubypeople/rdt/internal/ui/preferences Added Files: RubyTemplatePreferencePage.java Log Message: overhaul our completion proposal/template code. Now we will apply formatting to templates when inserted! Plus we're closer to the way JDT does things. We still can't use the actual code formatter on the templates (because our old one does a massive replace edit which messes up variables like the cursor placement). The end result is that users should create templates with somewhat proper formatting initially. --- NEW FILE: RubyTemplatePreferencePage.java --- /******************************************************************************* * Copyright (c) 2000, 2004 John-Mason P. Shackelford and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/cpl-v10.html * * Contributors: * John-Mason P. Shackelford - initial API and implementation * IBM Corporation - bug fixes *******************************************************************************/ package org.rubypeople.rdt.internal.ui.preferences; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.text.Document; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.source.SourceViewer; import org.eclipse.jface.text.source.SourceViewerConfiguration; import org.eclipse.jface.text.templates.Template; import org.eclipse.jface.text.templates.persistence.TemplatePersistenceData; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.widgets.Composite; import org.eclipse.ui.texteditor.templates.TemplatePreferencePage; import org.rubypeople.rdt.internal.ui.RubyPlugin; import org.rubypeople.rdt.internal.ui.text.template.contentassist.RubyTemplateAccess; import org.rubypeople.rdt.ui.PreferenceConstants; import org.rubypeople.rdt.ui.text.RubySourceViewerConfiguration; /** * @see org.eclipse.jface.preference.PreferencePage */ public class RubyTemplatePreferencePage extends TemplatePreferencePage { public RubyTemplatePreferencePage() { setPreferenceStore(RubyPlugin.getDefault().getPreferenceStore()); setTemplateStore(RubyTemplateAccess.getDefault().getTemplateStore()); setContextTypeRegistry(RubyTemplateAccess.getDefault().getContextTypeRegistry()); } /* * (non-Javadoc) * * @see org.eclipse.jface.preference.IPreferencePage#performOk() */ public boolean performOk() { boolean ok = super.performOk(); RubyPlugin.getDefault().savePluginPreferences(); return ok; } /* * (non-Javadoc) * * @see org.eclipse.ui.texteditor.templates.TemplatePreferencePage#createViewer(org.eclipse.swt.widgets.Composite) */ protected SourceViewer createViewer(Composite parent) { SourceViewer viewer = new SourceViewer(parent, null, null, false, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL); // FIXME Pass in the current editor! SourceViewerConfiguration configuration = new RubySourceViewerConfiguration(RubyPlugin.getDefault().getRubyTextTools(), null); IDocument document = new Document(); // FIXME Do we need this? //new AntDocumentSetupParticipant().setup(document); viewer.configure(configuration); viewer.setDocument(document); viewer.setEditable(false); Font font = JFaceResources.getFont(JFaceResources.TEXT_FONT); viewer.getTextWidget().setFont(font); return viewer; } /* * (non-Javadoc) * * @see org.eclipse.ui.texteditor.templates.TemplatePreferencePage#getFormatterPreferenceKey() */ protected String getFormatterPreferenceKey() { return PreferenceConstants.TEMPLATES_USE_CODEFORMATTER; } /* * @see org.eclipse.ui.texteditor.templates.TemplatePreferencePage#updateViewerInput() */ protected void updateViewerInput() { IStructuredSelection selection = (IStructuredSelection) getTableViewer().getSelection(); SourceViewer viewer = getViewer(); if (selection.size() == 1 && selection.getFirstElement() instanceof TemplatePersistenceData) { TemplatePersistenceData data = (TemplatePersistenceData) selection.getFirstElement(); Template template = data.getTemplate(); if (RubyPlugin.getDefault().getPreferenceStore().getBoolean(getFormatterPreferenceKey())) { String formatted = RubyPlugin.getDefault().getCodeFormatter().formatString(template.getPattern()); viewer.getDocument().set(formatted); } else { viewer.getDocument().set(template.getPattern()); } } else { viewer.getDocument().set(""); //$NON-NLS-1$ } } /* * (non-Javadoc) * * @see org.eclipse.ui.texteditor.templates.TemplatePreferencePage#isShowFormatterSetting() */ protected boolean isShowFormatterSetting() { return false; } } |
|
From: Christopher W. <caw...@us...> - 2006-02-18 16:53:56
|
Update of /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/template/ruby In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv28822/src/org/rubypeople/rdt/internal/corext/template/ruby Added Files: RubyScriptContextType.java RubyScriptContext.java RubyFormatter.java RubyContextType.java RubyContext.java RubyTemplateMessages.java Log Message: overhaul our completion proposal/template code. Now we will apply formatting to templates when inserted! Plus we're closer to the way JDT does things. We still can't use the actual code formatter on the templates (because our old one does a massive replace edit which messes up variables like the cursor placement). The end result is that users should create templates with somewhat proper formatting initially. --- NEW FILE: RubyScriptContext.java --- package org.rubypeople.rdt.internal.corext.template.ruby; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.templates.DocumentTemplateContext; import org.eclipse.jface.text.templates.TemplateContextType; import org.rubypeople.rdt.core.IRubyScript; import org.rubypeople.rdt.internal.ui.text.template.contentassist.MultiVariableGuess; public class RubyScriptContext extends DocumentTemplateContext { private IRubyScript fRubyScript; /** A flag to force evaluation in head-less mode. */ protected boolean fForceEvaluation; /** A global state for proposals that change if a master proposal changes. */ protected MultiVariableGuess fMultiVariableGuess; /** * Creates a ruby script context. * * @param type * the context type * @param document * the document * @param completionOffset * the completion position within the document * @param completionLength * the completion length within the document * @param rubyScript * the ruby script (may be <code>null</code>) */ protected RubyScriptContext(TemplateContextType type, IDocument document, int completionOffset, int completionLength, IRubyScript rubyScript) { super(type, document, completionOffset, completionLength); fRubyScript = rubyScript; } /** * Returns the ruby script if one is associated with this context, * <code>null</code> otherwise. * * @return the ruby script of this context or <code>null</code> */ public final IRubyScript getRubyScript() { return fRubyScript; } /** * Sets whether evaluation is forced or not. * * @param evaluate <code>true</code> in order to force evaluation, * <code>false</code> otherwise */ public void setForceEvaluation(boolean evaluate) { fForceEvaluation= evaluate; } /** * Returns the multi-variable guess. * * @return the multi-variable guess */ public MultiVariableGuess getMultiVariableGuess() { return fMultiVariableGuess; } /** * @param multiVariableGuess The multiVariableGuess to set. */ public void setMultiVariableGuess(MultiVariableGuess multiVariableGuess) { fMultiVariableGuess= multiVariableGuess; } } --- NEW FILE: RubyFormatter.java --- /******************************************************************************* * Copyright (c) 2000, 2005 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.rubypeople.rdt.internal.corext.template.ruby; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.Document; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITypedRegion; import org.eclipse.jface.text.templates.DocumentTemplateContext; import org.eclipse.jface.text.templates.GlobalTemplateVariables; import org.eclipse.jface.text.templates.TemplateBuffer; import org.eclipse.jface.text.templates.TemplateContext; import org.eclipse.jface.text.templates.TemplateVariable; import org.eclipse.text.edits.DeleteEdit; import org.eclipse.text.edits.InsertEdit; import org.eclipse.text.edits.MalformedTreeException; import org.eclipse.text.edits.MultiTextEdit; import org.eclipse.text.edits.RangeMarker; import org.eclipse.text.edits.ReplaceEdit; import org.eclipse.text.edits.TextEdit; import org.rubypeople.rdt.core.IRubyProject; import org.rubypeople.rdt.core.RubyCore; import org.rubypeople.rdt.core.formatter.CodeFormatter; import org.rubypeople.rdt.internal.corext.util.CodeFormatterUtil; import org.rubypeople.rdt.internal.corext.util.Strings; import org.rubypeople.rdt.internal.ui.RubyPlugin; import org.rubypeople.rdt.internal.ui.text.IRubyPartitions; import org.rubypeople.rdt.internal.ui.text.RubyHeuristicScanner; /** * A template editor using the Ruby formatter to format a template buffer. */ public class RubyFormatter { private static final String MARKER= "/*${" + GlobalTemplateVariables.Cursor.NAME + "}*/"; //$NON-NLS-1$ //$NON-NLS-2$ /** The line delimiter to use if code formatter is not used. */ private final String fLineDelimiter; /** The initial indent level */ private final int fInitialIndentLevel; /** The java partitioner */ private boolean fUseCodeFormatter; private final IRubyProject fProject; /** * Creates a RubyFormatter with the target line delimiter. * * @param lineDelimiter the line delimiter to use * @param initialIndentLevel the initial indentation level * @param useCodeFormatter <code>true</code> if the core code formatter should be used * @param project the java project from which to get the preferences, or <code>null</code> for workbench settings */ public RubyFormatter(String lineDelimiter, int initialIndentLevel, boolean useCodeFormatter, IRubyProject project) { fLineDelimiter= lineDelimiter; fUseCodeFormatter= useCodeFormatter; fInitialIndentLevel= initialIndentLevel; fProject= project; } /** * Formats the template buffer. * @param buffer * @param context * @throws BadLocationException */ public void format(TemplateBuffer buffer, TemplateContext context) throws BadLocationException { try { if (fUseCodeFormatter) // try to format and fall back to indenting try { format(buffer, (RubyContext) context); } catch (BadLocationException e) { indent(buffer); } catch (MalformedTreeException e) { indent(buffer); } else indent(buffer); // don't trim the buffer if the replacement area is empty // case: surrounding empty lines with block if (context instanceof DocumentTemplateContext) { DocumentTemplateContext dtc= (DocumentTemplateContext) context; if (dtc.getStart() == dtc.getCompletionOffset()) if (dtc.getDocument().get(dtc.getStart(), dtc.getEnd() - dtc.getStart()).trim().length() == 0) return; } trimBegin(buffer); } catch (MalformedTreeException e) { throw new BadLocationException(); } } private static int getCaretOffset(TemplateVariable[] variables) { for (int i= 0; i != variables.length; i++) { TemplateVariable variable= variables[i]; if (variable.getType().equals(GlobalTemplateVariables.Cursor.NAME)) return variable.getOffsets()[0]; } return -1; } private boolean isInsideCommentOrString(String string, int offset) { IDocument document= new Document(string); RubyPlugin.getDefault().getRubyTextTools().setupRubyDocumentPartitioner(document); try { ITypedRegion partition= document.getPartition(offset); String partitionType= partition.getType(); return partitionType != null && ( partitionType.equals(IRubyPartitions.RUBY_MULTI_LINE_COMMENT) || partitionType.equals(IRubyPartitions.RUBY_SINGLE_LINE_COMMENT) || partitionType.equals(IRubyPartitions.RUBY_STRING) || partitionType.equals(IRubyPartitions.RUBY_CHARACTER) || partitionType.equals(IRubyPartitions.RUBY_DOC)); } catch (BadLocationException e) { return false; } } private void format(TemplateBuffer templateBuffer, RubyContext context) throws BadLocationException { // XXX 4360, 15247 // workaround for code formatter limitations // handle a special case where cursor position is surrounded by whitespace String string= templateBuffer.getString(); TemplateVariable[] variables= templateBuffer.getVariables(); int caretOffset= getCaretOffset(variables); if ((caretOffset > 0) && Character.isWhitespace(string.charAt(caretOffset - 1)) && (caretOffset < string.length()) && Character.isWhitespace(string.charAt(caretOffset)) && ! isInsideCommentOrString(string, caretOffset)) { List positions= variablesToPositions(variables); TextEdit insert= new InsertEdit(caretOffset, MARKER); string= edit(string, positions, insert); positionsToVariables(positions, variables); templateBuffer.setContent(string, variables); try { plainFormat(templateBuffer, context); string= templateBuffer.getString(); variables= templateBuffer.getVariables(); caretOffset= getCaretOffset(variables); } finally { positions= variablesToPositions(variables); TextEdit delete= new DeleteEdit(caretOffset, MARKER.length()); string= edit(string, positions, delete); positionsToVariables(positions, variables); templateBuffer.setContent(string, variables); } } else { plainFormat(templateBuffer, context); } } private void plainFormat(TemplateBuffer templateBuffer, RubyContext context) throws BadLocationException { IDocument doc= new Document(templateBuffer.getString()); TemplateVariable[] variables= templateBuffer.getVariables(); List offsets= variablesToPositions(variables); Map options; if (context.getRubyScript() != null) options= context.getRubyScript().getRubyProject().getOptions(true); else options= RubyCore.getOptions(); String contents= doc.get(); int[] kinds= { CodeFormatter.K_EXPRESSION, CodeFormatter.K_STATEMENTS, CodeFormatter.K_UNKNOWN}; TextEdit edit= null; for (int i= 0; i < kinds.length && edit == null; i++) { edit= CodeFormatterUtil.format2(kinds[i], contents, fInitialIndentLevel, fLineDelimiter, options); } if (edit == null) throw new BadLocationException(); // fall back to indenting MultiTextEdit root; if (edit instanceof MultiTextEdit) root= (MultiTextEdit) edit; else { root= new MultiTextEdit(0, doc.getLength()); root.addChild(edit); } for (Iterator it= offsets.iterator(); it.hasNext();) { TextEdit position= (TextEdit) it.next(); try { root.addChild(position); } catch (MalformedTreeException e) { // position conflicts with formatter edit // ignore this position } } root.apply(doc, TextEdit.UPDATE_REGIONS); positionsToVariables(offsets, variables); templateBuffer.setContent(doc.get(), variables); } private void indent(TemplateBuffer templateBuffer) throws BadLocationException, MalformedTreeException { TemplateVariable[] variables= templateBuffer.getVariables(); List positions= variablesToPositions(variables); IDocument document= new Document(templateBuffer.getString()); MultiTextEdit root= new MultiTextEdit(0, document.getLength()); root.addChildren((TextEdit[]) positions.toArray(new TextEdit[positions.size()])); // first line int offset= document.getLineOffset(0); String indent = CodeFormatterUtil.createIndentString(fInitialIndentLevel, fProject); TextEdit edit= new InsertEdit(offset, indent); root.addChild(edit); root.apply(document, TextEdit.UPDATE_REGIONS); root.removeChild(edit); formatDelimiter(document, root, 0); // following lines int lineCount= document.getNumberOfLines(); RubyHeuristicScanner scanner= new RubyHeuristicScanner(document); // RubyIndenter indenter= new RubyIndenter(document, scanner, fProject); for (int line= 1; line < lineCount; line++) { IRegion region= document.getLineInformation(line); offset= region.getOffset(); // StringBuffer indent= indenter.computeIndentation(offset); if (indent == null) continue; // int nonWS= scanner.findNonWhitespaceForwardInAnyPartition(offset, offset + region.getLength()); // if (nonWS == RubyHeuristicScanner.NOT_FOUND) // nonWS= region.getLength() + offset; edit= new ReplaceEdit(offset, 0, indent.toString()); root.addChild(edit); root.apply(document, TextEdit.UPDATE_REGIONS); root.removeChild(edit); formatDelimiter(document, root, line); } positionsToVariables(positions, variables); templateBuffer.setContent(document.get(), variables); } /** * Changes the delimiter to the configured line delimiter. * * @param document the temporary document being edited * @param root the root edit containing all positions that will be updated along the way * @param line the line to format * @throws BadLocationException if applying the changes fails */ private void formatDelimiter(IDocument document, MultiTextEdit root, int line) throws BadLocationException { IRegion region= document.getLineInformation(line); String lineDelimiter= document.getLineDelimiter(line); if (lineDelimiter != null) { TextEdit edit= new ReplaceEdit(region.getOffset() + region.getLength(), lineDelimiter.length(), fLineDelimiter); root.addChild(edit); root.apply(document, TextEdit.UPDATE_REGIONS); root.removeChild(edit); } } private static void trimBegin(TemplateBuffer templateBuffer) throws BadLocationException { String string= templateBuffer.getString(); TemplateVariable[] variables= templateBuffer.getVariables(); List positions= variablesToPositions(variables); int i= 0; while ((i != string.length()) && Character.isWhitespace(string.charAt(i))) i++; string= edit(string, positions, new DeleteEdit(0, i)); positionsToVariables(positions, variables); templateBuffer.setContent(string, variables); } private static String edit(String string, List positions, TextEdit edit) throws BadLocationException { MultiTextEdit root= new MultiTextEdit(0, string.length()); root.addChildren((TextEdit[]) positions.toArray(new TextEdit[positions.size()])); root.addChild(edit); IDocument document= new Document(string); root.apply(document); return document.get(); } private static List variablesToPositions(TemplateVariable[] variables) { List positions= new ArrayList(5); for (int i= 0; i != variables.length; i++) { int[] offsets= variables[i].getOffsets(); // trim positions off whitespace String value= variables[i].getDefaultValue(); int wsStart= 0; while (wsStart < value.length() && Character.isWhitespace(value.charAt(wsStart)) && !Strings.isLineDelimiterChar(value.charAt(wsStart))) wsStart++; variables[i].getValues()[0]= value.substring(wsStart); for (int j= 0; j != offsets.length; j++) { offsets[j] += wsStart; positions.add(new RangeMarker(offsets[j], 0)); } } return positions; } private static void positionsToVariables(List positions, TemplateVariable[] variables) { Iterator iterator= positions.iterator(); for (int i= 0; i != variables.length; i++) { TemplateVariable variable= variables[i]; int[] offsets= new int[variable.getOffsets().length]; for (int j= 0; j != offsets.length; j++) offsets[j]= ((TextEdit) iterator.next()).getOffset(); variable.setOffsets(offsets); } } } --- NEW FILE: RubyContext.java --- /******************************************************************************* * Copyright (c) 2004 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/cpl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.rubypeople.rdt.internal.corext.template.ruby; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.TextUtilities; import org.eclipse.jface.text.templates.Template; import org.eclipse.jface.text.templates.TemplateBuffer; import org.eclipse.jface.text.templates.TemplateContextType; import org.eclipse.jface.text.templates.TemplateException; import org.eclipse.jface.text.templates.TemplateTranslator; import org.eclipse.jface.text.templates.TemplateVariable; import org.rubypeople.rdt.core.IRubyProject; import org.rubypeople.rdt.core.IRubyScript; import org.rubypeople.rdt.internal.corext.util.Strings; import org.rubypeople.rdt.internal.ui.RubyPlugin; import org.rubypeople.rdt.internal.ui.text.template.contentassist.MultiVariable; import org.rubypeople.rdt.ui.PreferenceConstants; public class RubyContext extends RubyScriptContext { /** * Creates a ruby template context. * * @param type * the context type. * @param document * the document. * @param completionOffset * the completion offset within the document. * @param completionLength * the completion length. * @param compilationUnit * the compilation unit (may be <code>null</code>). */ public RubyContext(TemplateContextType type, IDocument document, int completionOffset, int completionLength, IRubyScript compilationUnit) { super(type, document, completionOffset, completionLength, compilationUnit); } /* * (non-Javadoc) * * @see org.eclipse.jface.text.templates.TemplateContext#evaluate(org.eclipse.jface.text.templates.Template) */ public TemplateBuffer evaluate(Template template) throws BadLocationException, TemplateException { if (!canEvaluate(template)) throw new TemplateException( RubyTemplateMessages.Context_error_cannot_evaluate); TemplateTranslator translator = new TemplateTranslator() { /* * @see org.eclipse.jface.text.templates.TemplateTranslator#createVariable(java.lang.String, * java.lang.String, int[]) */ protected TemplateVariable createVariable(String type, String name, int[] offsets) { return new MultiVariable(type, name, offsets); } }; TemplateBuffer buffer = translator.translate(template); getContextType().resolve(buffer, this); IPreferenceStore prefs = RubyPlugin.getDefault().getPreferenceStore(); boolean useCodeFormatter = prefs .getBoolean(PreferenceConstants.TEMPLATES_USE_CODEFORMATTER); IRubyProject project = getRubyScript() != null ? getRubyScript() .getRubyProject() : null; RubyFormatter formatter = new RubyFormatter(TextUtilities .getDefaultLineDelimiter(getDocument()), getIndentation(), useCodeFormatter, project); formatter.format(buffer, this); return buffer; } /** * Returns the indentation level at the position of code completion. * * @return the indentation level at the position of the code completion */ private int getIndentation() { int start = getStart(); IDocument document = getDocument(); try { IRegion region = document.getLineInformationOfOffset(start); String lineContent = document.get(region.getOffset(), region .getLength()); IRubyScript compilationUnit = getRubyScript(); IRubyProject project = compilationUnit == null ? null : compilationUnit.getRubyProject(); return Strings.computeIndentUnits(lineContent, project); } catch (BadLocationException e) { return 0; } } /* * @see TemplateContext#canEvaluate(Template templates) */ public boolean canEvaluate(Template template) { if (fForceEvaluation) return true; String key = getKey(); return template.matches(key, getContextType().getId()) && key.length() != 0 && template.getName().toLowerCase().startsWith( key.toLowerCase()); } /* * @see org.eclipse.jdt.internal.corext.template.DocumentTemplateContext#getKey() */ public String getKey() { if (getCompletionLength() == 0) return super.getKey(); try { IDocument document = getDocument(); int start = getStart(); int end = getCompletionOffset(); return start <= end ? document.get(start, end - start) : ""; //$NON-NLS-1$ } catch (BadLocationException e) { return super.getKey(); } } /* * (non-Javadoc) * * @see org.eclipse.jface.text.templates.DocumentTemplateContext#getEnd() */ public int getEnd() { if (getCompletionLength() == 0) return super.getEnd(); try { IDocument document = getDocument(); int start = getCompletionOffset(); int end = getCompletionOffset() + getCompletionLength(); while (start != end && Character.isWhitespace(document.getChar(end - 1))) end--; return end; } catch (BadLocationException e) { return super.getEnd(); } } /* * (non-Javadoc) * * @see org.eclipse.jface.text.templates.DocumentTemplateContext#getStart() */ public int getStart() { try { IDocument document = getDocument(); int start = getCompletionOffset(); int end = getCompletionOffset() + getCompletionLength(); while (start != 0 && Character.isUnicodeIdentifierPart(document .getChar(start - 1))) start--; while (start != end && Character.isWhitespace(document.getChar(start))) start++; if (start == end) start = getCompletionOffset(); return start; } catch (BadLocationException e) { return super.getStart(); } } } --- NEW FILE: RubyContextType.java --- package org.rubypeople.rdt.internal.corext.template.ruby; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.templates.GlobalTemplateVariables; import org.rubypeople.rdt.core.IRubyScript; public class RubyContextType extends RubyScriptContextType { public static final String NAME = "ruby"; //$NON-NLS-1$ /** * Creates a ruby context type. */ public RubyContextType() { super(NAME); // global addResolver(new GlobalTemplateVariables.Cursor()); addResolver(new GlobalTemplateVariables.WordSelection()); addResolver(new GlobalTemplateVariables.LineSelection()); addResolver(new GlobalTemplateVariables.Dollar()); addResolver(new GlobalTemplateVariables.Date()); addResolver(new GlobalTemplateVariables.Year()); addResolver(new GlobalTemplateVariables.Time()); addResolver(new GlobalTemplateVariables.User()); } /* * (non-Javadoc) * * @see org.rubypeople.rdt.internal.corext.template.ruby.RubyFileContextType#createContext(org.eclipse.jface.text.IDocument, * int, int, org.rubypeople.rdt.core.IRubyScript) */ public RubyScriptContext createContext(IDocument document, int offset, int length, IRubyScript script) { return new RubyContext(this, document, offset, length, script); } } --- NEW FILE: RubyTemplateMessages.java --- package org.rubypeople.rdt.internal.corext.template.ruby; import org.eclipse.osgi.util.NLS; public class RubyTemplateMessages extends NLS { private static final String BUNDLE_NAME = RubyTemplateMessages.class .getName(); private RubyTemplateMessages() { // Do not instantiate } public static String ContextType_error_multiple_cursor_variables; public static String Context_error_cannot_evaluate; static { NLS.initializeMessages(BUNDLE_NAME, RubyTemplateMessages.class); } } --- NEW FILE: RubyScriptContextType.java --- /******************************************************************************* * Copyright (c) 2000, 2004 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/cpl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.rubypeople.rdt.internal.corext.template.ruby; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.templates.GlobalTemplateVariables; import org.eclipse.jface.text.templates.TemplateContextType; import org.eclipse.jface.text.templates.TemplateException; import org.eclipse.jface.text.templates.TemplateVariable; import org.rubypeople.rdt.core.IRubyScript; /** * A very simple context type. */ public abstract class RubyScriptContextType extends TemplateContextType { /** * Creates a new Ruby context type. */ public RubyScriptContextType(String name) { super(name); } public abstract RubyScriptContext createContext(IDocument document, int completionPosition, int length, IRubyScript script); /* * (non-Javadoc) * * @see org.eclipse.jdt.internal.corext.template.ContextType#validateVariables(org.eclipse.jdt.internal.corext.template.TemplateVariable[]) */ protected void validateVariables(TemplateVariable[] variables) throws TemplateException { // check for multiple cursor variables for (int i = 0; i < variables.length; i++) { TemplateVariable var = variables[i]; if (var.getType().equals(GlobalTemplateVariables.Cursor.NAME)) { if (var.getOffsets().length > 1) { throw new TemplateException( RubyTemplateMessages.ContextType_error_multiple_cursor_variables); } } } } } |
|
From: Christopher W. <caw...@us...> - 2006-02-18 16:53:55
|
Update of /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/text/ruby In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv28822/src/org/rubypeople/rdt/ui/text/ruby Added Files: IRubyCompletionProposal.java Log Message: overhaul our completion proposal/template code. Now we will apply formatting to templates when inserted! Plus we're closer to the way JDT does things. We still can't use the actual code formatter on the templates (because our old one does a massive replace edit which messes up variables like the cursor placement). The end result is that users should create templates with somewhat proper formatting initially. --- NEW FILE: IRubyCompletionProposal.java --- /******************************************************************************* * Copyright (c) 2000, 2005 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.rubypeople.rdt.ui.text.ruby; import org.eclipse.jface.text.contentassist.ICompletionProposal; /** * A completion proposal with a relevance value. * The relevance value is used to sort the completion proposals. Proposals with higher relevance * should be listed before proposals with lower relevance. * <p> * This interface can be implemented by clients. * </p> * * @see org.eclipse.jface.text.contentassist.ICompletionProposal * @since 0.8.0 */ public interface IRubyCompletionProposal extends ICompletionProposal { /** * Returns the relevance of this completion proposal. * <p> * The relevance is used to determine if this proposal is more * relevant than another proposal.</p> * * @return the relevance of this completion proposal in the range of [0, 100] */ int getRelevance(); } |
|
From: Christopher W. <caw...@us...> - 2006-02-18 16:53:55
|
Update of /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv28822/src/org/rubypeople/rdt/internal/corext/util Modified Files: CodeFormatterUtil.java Added Files: Strings.java Log Message: overhaul our completion proposal/template code. Now we will apply formatting to templates when inserted! Plus we're closer to the way JDT does things. We still can't use the actual code formatter on the templates (because our old one does a massive replace edit which messes up variables like the cursor placement). The end result is that users should create templates with somewhat proper formatting initially. Index: CodeFormatterUtil.java =================================================================== RCS file: /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/CodeFormatterUtil.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** CodeFormatterUtil.java 17 Feb 2006 20:23:22 -0000 1.1 --- CodeFormatterUtil.java 18 Feb 2006 16:53:51 -0000 1.2 *************** *** 4,8 **** --- 4,12 ---- import org.eclipse.text.edits.TextEdit; + import org.rubypeople.rdt.core.IRubyProject; + import org.rubypeople.rdt.core.RubyCore; import org.rubypeople.rdt.core.ToolFactory; + import org.rubypeople.rdt.core.formatter.DefaultCodeFormatterConstants; + import org.rubypeople.rdt.internal.corext.Assert; public class CodeFormatterUtil { *************** *** 25,27 **** --- 29,169 ---- indentationLevel, lineSeparator); } + + /** + * Returns the current indent width. + * + * @param project + * the project where the source is used or <code>null</code> if + * the project is unknown and the workspace default should be + * used + * @return the indent width + * @since 0.8.0 + */ + public static int getIndentWidth(IRubyProject project) { + String key; + if (DefaultCodeFormatterConstants.MIXED.equals(getCoreOption(project, + DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR))) + key = DefaultCodeFormatterConstants.FORMATTER_INDENTATION_SIZE; + else + key = DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE; + + return getCoreOption(project, key, 4); + } + + /** + * Gets the current tab width. + * + * @param project + * The project where the source is used, used for project + * specific options or <code>null</code> if the project is + * unknown and the workspace default should be used + * @return The tab width + */ + public static int getTabWidth(IRubyProject project) { + /* + * If the tab-char is SPACE, FORMATTER_INDENTATION_SIZE is not used by + * the core formatter. We piggy back the visual tab length setting in + * that preference in that case. + */ + String key; + if (RubyCore.SPACE.equals(getCoreOption(project, + DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR))) + key = DefaultCodeFormatterConstants.FORMATTER_INDENTATION_SIZE; + else + key = DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE; + + return getCoreOption(project, key, 4); + } + + /** + * Returns the possibly <code>project</code>-specific core preference + * defined under <code>key</code>. + * + * @param project + * the project to get the preference from, or <code>null</code> + * to get the global preference + * @param key + * the key of the preference + * @return the value of the preference + * @since 0.8.0 + */ + private static String getCoreOption(IRubyProject project, String key) { + if (project == null) return RubyCore.getOption(key); + return project.getOption(key, true); + } + + /** + * Returns the possibly <code>project</code>-specific core preference + * defined under <code>key</code>, or <code>def</code> if the value is + * not a integer. + * + * @param project + * the project to get the preference from, or <code>null</code> + * to get the global preference + * @param key + * the key of the preference + * @param def + * the default value + * @return the value of the preference + * @since 0.8.0 + */ + private static int getCoreOption(IRubyProject project, String key, int def) { + try { + return Integer.parseInt(getCoreOption(project, key)); + } catch (NumberFormatException e) { + return def; + } + } + + /** + * Creates a string that represents the given number of indentation units. + * The returned string can contain tabs and/or spaces depending on the core + * formatter preferences. + * + * @param indentationUnits + * the number of indentation units to generate + * @param project + * the project from which to get the formatter settings, + * <code>null</code> if the workspace default should be used + * @return the indent string + */ + public static String createIndentString(int indentationUnits, IRubyProject project) { + final String tabChar = getCoreOption(project, + DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR); + final int tabs, spaces; + if (RubyCore.SPACE.equals(tabChar)) { + tabs = 0; + spaces = indentationUnits * getIndentWidth(project); + } else if (RubyCore.TAB.equals(tabChar)) { + // indentWidth == tabWidth + tabs = indentationUnits; + spaces = 0; + } else if (DefaultCodeFormatterConstants.MIXED.equals(tabChar)) { + int tabWidth = getTabWidth(project); + int spaceEquivalents = indentationUnits * getIndentWidth(project); + if (tabWidth > 0) { + tabs = spaceEquivalents / tabWidth; + spaces = spaceEquivalents % tabWidth; + } else { + tabs = 0; + spaces = spaceEquivalents; + } + } else { + // new indent type not yet handled + Assert.isTrue(false); + return null; + } + + StringBuffer buffer = new StringBuffer(tabs + spaces); + for (int i = 0; i < tabs; i++) + buffer.append('\t'); + for (int i = 0; i < spaces; i++) + buffer.append(' '); + return buffer.toString(); + } + + public static TextEdit format2(int kind, String string, int indentationLevel, + String lineSeparator, Map options) { + return format2(kind, string, 0, string.length(), indentationLevel, lineSeparator, options); + } } --- NEW FILE: Strings.java --- package org.rubypeople.rdt.internal.corext.util; import org.rubypeople.rdt.core.IRubyProject; public class Strings { /** * Returns the indent of the given string in indentation units. Odd spaces * are not counted. * * @param line * the text line * @param project * the ruby project from which to get the formatter preferences, * or <code>null</code> for global preferences * @since 3.1 */ public static int computeIndentUnits(String line, IRubyProject project) { return computeIndentUnits(line, CodeFormatterUtil.getTabWidth(project), CodeFormatterUtil .getIndentWidth(project)); } /** * Returns the indent of the given string in indentation units. Odd spaces * are not counted. * * @param line * the text line * @param tabWidth * the width of the '\t' character in space equivalents * @param indentWidth * the width of one indentation unit in space equivalents * @since 3.1 */ public static int computeIndentUnits(String line, int tabWidth, int indentWidth) { if (indentWidth == 0) return -1; int visualLength = measureIndentLength(line, tabWidth); return visualLength / indentWidth; } /** * Computes the visual length of the indentation of a * <code>CharSequence</code>, counting a tab character as the size until * the next tab stop and every other whitespace character as one. * * @param line * the string to measure the indent of * @param tabSize * the visual size of a tab in space equivalents * @return the visual length of the indentation of <code>line</code> * @since 3.1 */ public static int measureIndentLength(CharSequence line, int tabSize) { int length = 0; int max = line.length(); for (int i = 0; i < max; i++) { char ch = line.charAt(i); if (ch == '\t') { int reminder = length % tabSize; length += tabSize - reminder; } else if (isIndentChar(ch)) { length++; } else { return length; } } return length; } /** * Indent char is a space char but not a line delimiters. * <code>== Character.isWhitespace(ch) && ch != '\n' && ch != '\r'</code> */ public static boolean isIndentChar(char ch) { return Character.isWhitespace(ch) && !isLineDelimiterChar(ch); } /** * Line delimiter chars are '\n' and '\r'. */ public static boolean isLineDelimiterChar(char ch) { return ch == '\n' || ch == '\r'; } } |
Update of /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv28822/src/org/rubypeople/rdt/internal/ui/text/ruby Modified Files: RubyFormattingStrategy.java RubyCompletionProcessor.java RubyReconcilingStrategy.java Added Files: RubyCompletionProposal.java Log Message: overhaul our completion proposal/template code. Now we will apply formatting to templates when inserted! Plus we're closer to the way JDT does things. We still can't use the actual code formatter on the templates (because our old one does a massive replace edit which messes up variables like the cursor placement). The end result is that users should create templates with somewhat proper formatting initially. Index: RubyReconcilingStrategy.java =================================================================== RCS file: /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/RubyReconcilingStrategy.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** RubyReconcilingStrategy.java 10 Feb 2006 19:54:19 -0000 1.1 --- RubyReconcilingStrategy.java 18 Feb 2006 16:53:51 -0000 1.2 *************** *** 100,104 **** } public void handleException(Throwable ex) { ! IStatus status= new Status(IStatus.ERROR, RubyUI.ID_PLUGIN, IStatus.OK, "Error in JDT Core during reconcile", ex); //$NON-NLS-1$ RubyPlugin.getDefault().getLog().log(status); } --- 100,104 ---- } public void handleException(Throwable ex) { ! IStatus status= new Status(IStatus.ERROR, RubyUI.ID_PLUGIN, IStatus.OK, "Error in RDT Core during reconcile", ex); //$NON-NLS-1$ RubyPlugin.getDefault().getLog().log(status); } --- NEW FILE: RubyCompletionProposal.java --- package org.rubypeople.rdt.internal.ui.text.ruby; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.contentassist.IContextInformation; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.rubypeople.rdt.ui.text.ruby.IRubyCompletionProposal; public class RubyCompletionProposal implements IRubyCompletionProposal { private String completion; private int start; private int length; private int relevance; private String label; private Image image; public RubyCompletionProposal(String completion, int start, int length, Image image, String label, int relevance) { this.completion = completion; this.start = start; this.length = length; this.label = label; this.image = image; this.relevance = relevance; } public int getRelevance() { return relevance; } public void apply(IDocument document) { // TODO Auto-generated method stub } public Point getSelection(IDocument document) { // TODO Auto-generated method stub return null; } public String getAdditionalProposalInfo() { // TODO Auto-generated method stub return null; } public String getDisplayString() { return label; } public Image getImage() { return image; } public IContextInformation getContextInformation() { // TODO Auto-generated method stub return null; } } Index: RubyFormattingStrategy.java =================================================================== RCS file: /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/RubyFormattingStrategy.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** RubyFormattingStrategy.java 10 Feb 2006 19:54:19 -0000 1.1 --- RubyFormattingStrategy.java 18 Feb 2006 16:53:51 -0000 1.2 *************** *** 30,34 **** * Formatting strategy for ruby source code. * ! * @since 3.0 */ public class RubyFormattingStrategy extends ContextBasedFormattingStrategy { --- 30,34 ---- * Formatting strategy for ruby source code. * ! * @since 0.8.0 */ public class RubyFormattingStrategy extends ContextBasedFormattingStrategy { *************** *** 40,44 **** /** ! * Creates a new java formatting strategy. */ public RubyFormattingStrategy() { --- 40,44 ---- /** ! * Creates a new ruby formatting strategy. */ public RubyFormattingStrategy() { Index: RubyCompletionProcessor.java =================================================================== RCS file: /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/RubyCompletionProcessor.java,v retrieving revision 1.15 retrieving revision 1.16 diff -C2 -d -r1.15 -r1.16 *** RubyCompletionProcessor.java 29 Nov 2005 19:42:03 -0000 1.15 --- RubyCompletionProcessor.java 18 Feb 2006 16:53:51 -0000 1.16 *************** *** 5,8 **** --- 5,9 ---- import java.util.Arrays; import java.util.Collection; + import java.util.Collections; import java.util.Iterator; import java.util.List; *************** *** 19,22 **** --- 20,24 ---- import org.eclipse.jface.text.contentassist.IContextInformationPresenter; import org.eclipse.jface.text.contentassist.IContextInformationValidator; + import org.eclipse.jface.text.contentassist.TextContentAssistInvocationContext; import org.eclipse.jface.text.templates.Template; import org.eclipse.jface.text.templates.TemplateCompletionProcessor; *************** *** 29,405 **** import org.rubypeople.rdt.core.IRubyScript; import org.rubypeople.rdt.core.RubyModelException; import org.rubypeople.rdt.internal.ui.RubyPlugin; import org.rubypeople.rdt.internal.ui.RubyPluginImages; - import org.rubypeople.rdt.internal.ui.rubyeditor.templates.RubyFileContextType; - import org.rubypeople.rdt.internal.ui.rubyeditor.templates.RubyTemplateAccess; import org.rubypeople.rdt.internal.ui.text.RubyTextTools; import org.rubypeople.rdt.ui.IWorkingCopyManager; ! public class RubyCompletionProcessor extends TemplateCompletionProcessor implements ! IContentAssistProcessor { ! private static String[] keywordProposals; ! protected IContextInformationValidator contextInformationValidator = new RubyContextInformationValidator(); ! private static String[] preDefinedGlobals = { "$!", "$@", "$_", "$.", "$&", "$n", "$~", "$=", ! "$/", "$\\", "$0", "$*", "$$", "$?", "$:"}; ! private static String[] globalContexts = { "error message", "position of an error occurrence", ! "latest read string by `gets'", "latest read number of line by interpreter", ! "latest matched string by the regexep.", ! "latest matched string by nth parentheses of regexp.", ! "data for latest matche for regexp", ! "whether or not case-sensitive in string matching", "input record separator", ! "output record separator", "the name of the ruby scpript file", ! "command line arguments for the ruby scpript", "PID for ruby interpreter", ! "status of the latest executed child process", ! "array of paths that ruby interpreter searches for files"}; ! // FIXME This is an ugly hack, just hard-coding method names ! // FIXME Create a model for Ruby core in our Ruby Model! ! private static String[] KERNEL_METHODS = { "abort", "at_exit", "autoload", "binding", ! "block_given?", "callcc", "caller", "catch", "chomp", "chomp!", "chop", "chop!", ! "eval", "exec", "exit", "exit!", "fail", "fork", "format", "gets", "global_variables", ! "gsub", "gsub!", "iterator?", "lambda", "load", "local_variables", "loop", "open", "p", ! "print", "printf", "proc", "putc", "puts", "raise", "rand", "readline", "readlines", ! "require", "scan", "select", "set_trace_func", "singleton_method_added", "sleep", ! "split", "sprintf", "srand", "sub", "sub!", "syscall", "system", "test", "throw", ! "trace_var", "trap", "untrace_var"}; ! /** ! * The prefix for the current content assist ! */ ! protected String currentPrefix = null; ! /** ! * Cursor position, counted from the beginning of the document. ! * <P> ! * The first position has index '0'. ! */ ! protected int cursorPosition = -1; ! /** ! * The text viewer. ! */ ! private ITextViewer viewer; ! private IWorkingCopyManager fManager; ! private IEditorPart fEditor; ! public RubyCompletionProcessor(IEditorPart editor) { ! super(); ! fEditor = editor; ! fManager = RubyPlugin.getDefault().getWorkingCopyManager(); ! } ! public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int documentOffset) { ! this.viewer = viewer; ! ITextSelection selection = (ITextSelection) viewer.getSelectionProvider().getSelection(); ! cursorPosition = selection.getOffset() + selection.getLength(); ! ICompletionProposal[] normal = determineRubyElementProposals(viewer, documentOffset); ! ICompletionProposal[] templates = determineTemplateProposals(viewer, documentOffset); ! ICompletionProposal[] merged = merge(normal, templates); ! ICompletionProposal[] keywords = determineKeywordProposals(viewer, documentOffset); ! ICompletionProposal[] mergedTwo = merge(merged, keywords); ! return mergedTwo; ! } ! /** ! * @param arrayOne ! * @param arrayTwo ! * @return ! */ ! private ICompletionProposal[] merge(ICompletionProposal[] arrayOne, ! ICompletionProposal[] arrayTwo) { ! ICompletionProposal[] merged = new ICompletionProposal[arrayOne.length + arrayTwo.length]; ! System.arraycopy(arrayOne, 0, merged, 0, arrayOne.length); ! System.arraycopy(arrayTwo, 0, merged, arrayOne.length, arrayTwo.length); ! return merged; ! } ! /** ! * @param viewer ! * @param documentOffset ! * @return ! */ ! private ICompletionProposal[] determineRubyElementProposals(ITextViewer viewer, ! int documentOffset) { ! Collection completionProposals = getDocumentsRubyElements(); ! String prefix = getCurrentPrefix(viewer.getDocument().get(), documentOffset); ! // following the JDT convention, if there's no text already entered, ! // then don't suggest imported elements ! if (prefix.length() > 0) { ! // FIXME Add elements from required/loaded files! ! } ! List possibleProposals = new ArrayList(); ! for (Iterator iter = completionProposals.iterator(); iter.hasNext();) { ! String proposal = (String) iter.next(); ! if (proposal.startsWith(prefix)) { ! String message = "{0}"; ! IContextInformation info = new ContextInformation(proposal, MessageFormat.format( ! message, new Object[] { proposal})); ! possibleProposals.add(new CompletionProposal(proposal.substring(prefix.length(), ! proposal.length()), documentOffset, 0, proposal.length() - prefix.length(), ! null, proposal, info, MessageFormat.format("Ruby keyword: {0}", ! new Object[] { proposal}))); ! } ! } ! ICompletionProposal[] result = new ICompletionProposal[possibleProposals.size()]; ! possibleProposals.toArray(result); ! return result; ! } ! private Collection addKernelMethods() { ! Collection kernelProposals = new ArrayList(); ! for (int i = 0; i < KERNEL_METHODS.length; i++) { ! kernelProposals.add(KERNEL_METHODS[i]); ! } ! return kernelProposals; ! } ! /* ! * (non-Javadoc) ! * ! * @see org.eclipse.jface.text.templates.TemplateCompletionProcessor#getImage(org.eclipse.jface.text.templates.Template) ! */ ! protected Image getImage(Template template) { ! return RubyPluginImages.get(RubyPluginImages.IMG_TEMPLATE_PROPOSAL); ! } ! /* ! * (non-Javadoc) ! * ! * @see org.eclipse.jface.text.templates.TemplateCompletionProcessor#getContextType(org.eclipse.jface.text.ITextViewer, ! * org.eclipse.jface.text.IRegion) ! */ ! protected TemplateContextType getContextType(ITextViewer textViewer, IRegion region) { ! return RubyTemplateAccess.getDefault().getContextTypeRegistry().getContextType( ! RubyFileContextType.RUBYFILE_CONTEXT_TYPE); ! } ! /** ! * @return ! */ ! private ICompletionProposal[] determineTemplateProposals(ITextViewer refViewer, ! int documentOffset) { ! String prefix = getCurrentPrefix(viewer.getDocument().get(), documentOffset); ! ICompletionProposal[] matchingTemplateProposals; ! if (prefix.length() == 0) { ! matchingTemplateProposals = super.computeCompletionProposals(refViewer, documentOffset); ! } else { ! ICompletionProposal[] templateProposals = super.computeCompletionProposals(refViewer, ! documentOffset); ! List templateProposalList = new ArrayList(templateProposals.length); ! for (int i = 0; i < templateProposals.length; i++) { ! if (templateProposals[i].getDisplayString().toLowerCase().startsWith(prefix)) { ! templateProposalList.add(templateProposals[i]); ! } ! } ! matchingTemplateProposals = (ICompletionProposal[]) templateProposalList ! .toArray(new ICompletionProposal[templateProposalList.size()]); ! } ! return matchingTemplateProposals; ! } ! /** ! * @param proposal ! * @return ! */ ! private String getContext(String proposal) { ! for (int i = 0; i < preDefinedGlobals.length; i++) { ! if (proposal.equals(preDefinedGlobals[i])) return globalContexts[i]; ! } ! return ""; ! } ! /** ! * @param proposal ! * @return ! */ ! private boolean isPredefinedGlobal(String proposal) { ! for (int i = 0; i < preDefinedGlobals.length; i++) { ! if (proposal.equals(preDefinedGlobals[i])) return true; ! } ! return false; ! } ! /** ! * Gets all the distinct elements in the current RubyScript ! * ! * @return a List of the names of all the elements in the current RubyScript ! */ ! private Collection getDocumentsRubyElements() { ! IRubyScript script = fManager.getWorkingCopy(fEditor.getEditorInput()); ! // FIXME Get only the elements in the current scope! ! Collection elements = getElements(script); ! IRubyProject project = script.getRubyProject(); ! // Add all the classes and modules in the project ! elements.addAll(addClassesAndModulesInProject(project)); ! // Add all the classes and modules in referenced projects ! for (Iterator iter = project.getReferencedProjects().iterator(); iter.hasNext();) { ! elements.addAll(addClassesAndModulesInProject(((IRubyProject) iter.next()))); ! } ! // TODO Add all the methods defined in included modules for the class ! // TODO Add all the methods defined in superclasses for the class/module ! // always add Kernel methods ! elements.addAll(addKernelMethods()); ! return elements; ! } ! private Collection addClassesAndModulesInProject(IRubyProject project) { ! return getElementsOfType(project, new int[] { IRubyElement.TYPE}); ! } ! private Collection getElementsOfType(IParent element, int[] types) { ! Collection suggestions = new ArrayList(); ! try { ! IRubyElement[] elements = element.getChildren(); ! if (elements == null) return suggestions; ! for (int x = 0; x < elements.length; x++) { ! IRubyElement child = elements[x]; ! for (int i = 0; i < types.length; i++) { ! if (child.getElementType() == types[i]) { ! suggestions.add(child.getElementName()); ! break; ! } ! } ! if (child instanceof IParent) ! suggestions.addAll(getElementsOfType((IParent) child, types)); ! } ! } catch (RubyModelException e) { ! e.printStackTrace(); ! } ! return suggestions; ! } ! /** ! * @param script ! * @return ! */ ! private Collection getElements(IParent element) { ! return getElementsOfType(element, new int[] { IRubyElement.TYPE, IRubyElement.METHOD, ! IRubyElement.GLOBAL, IRubyElement.CONSTANT, IRubyElement.CLASS_VAR, ! IRubyElement.INSTANCE_VAR}); ! } ! private ICompletionProposal[] determineKeywordProposals(ITextViewer viewer, int documentOffset) { ! initKeywordProposals(); ! String prefix = getCurrentPrefix(viewer.getDocument().get(), documentOffset); ! // following the JDT convention, if there's no text already entered, ! // then don't suggest keywords ! if (prefix.length() < 1) { return new ICompletionProposal[0]; } ! List completionProposals = Arrays.asList(keywordProposals); ! // FIXME Refactor to combine the copied code in ! // determineRubyElementProposals ! List possibleProposals = new ArrayList(); ! for (int i = 0; i < completionProposals.size(); i++) { ! String proposal = (String) completionProposals.get(i); ! if (proposal.startsWith(prefix)) { ! String message; ! if (isPredefinedGlobal(proposal)) { ! message = "{0} " + getContext(proposal); ! } else { ! message = "{0}"; ! } ! IContextInformation info = new ContextInformation(proposal, MessageFormat.format( ! message, new Object[] { proposal})); ! possibleProposals.add(new CompletionProposal(proposal.substring(prefix.length(), ! proposal.length()), documentOffset, 0, proposal.length() - prefix.length(), ! null, proposal, info, MessageFormat.format("Ruby keyword: {0}", ! new Object[] { proposal}))); ! } ! } ! ICompletionProposal[] result = new ICompletionProposal[possibleProposals.size()]; ! possibleProposals.toArray(result); ! return result; ! } ! /** ! * ! */ ! private void initKeywordProposals() { ! if (keywordProposals == null) { ! String[] keywords = RubyTextTools.getKeyWords(); ! keywordProposals = new String[keywords.length + preDefinedGlobals.length]; ! System.arraycopy(keywords, 0, keywordProposals, 0, keywords.length); ! System.arraycopy(preDefinedGlobals, 0, keywordProposals, keywords.length, ! preDefinedGlobals.length); ! } ! } ! protected String getCurrentPrefix(String documentString, int documentOffset) { ! int tokenLength = 0; ! while ((documentOffset - tokenLength > 0) ! && !Character.isWhitespace(documentString.charAt(documentOffset - tokenLength - 1))) ! tokenLength++; ! return documentString.substring((documentOffset - tokenLength), documentOffset); ! } ! /* ! * (non-Javadoc) ! * ! * @see org.eclipse.jface.text.templates.TemplateCompletionProcessor#getTemplates(java.lang.String) ! */ ! protected Template[] getTemplates(String contextTypeId) { ! return RubyTemplateAccess.getDefault().getTemplateStore().getTemplates(); ! } ! public IContextInformation[] computeContextInformation(ITextViewer viewer, int documentOffset) { ! return null; ! } ! public char[] getCompletionProposalAutoActivationCharacters() { ! return null; ! } ! public char[] getContextInformationAutoActivationCharacters() { ! return new char[] { '#'}; ! } ! public IContextInformationValidator getContextInformationValidator() { ! return contextInformationValidator; ! } ! public String getErrorMessage() { ! return null; ! } ! protected class RubyContextInformationValidator implements IContextInformationValidator, ! IContextInformationPresenter { ! protected int installDocumentPosition; ! /** ! * @see org.eclipse.jface.text.contentassist.IContextInformationPresenter#install(IContextInformation, ! * ITextViewer, int) ! */ ! public void install(IContextInformation info, ITextViewer viewer, int documentPosition) { ! installDocumentPosition = documentPosition; ! } ! /** ! * @see org.eclipse.jface.text.contentassist.IContextInformationValidator#isContextInformationValid(int) ! */ ! public boolean isContextInformationValid(int documentPosition) { ! return Math.abs(installDocumentPosition - documentPosition) < 1; ! } ! /** ! * @see org.eclipse.jface.text.contentassist.IContextInformationPresenter#updatePresentation(int, ! * TextPresentation) ! */ ! public boolean updatePresentation(int documentPosition, TextPresentation presentation) { ! return false; ! } ! } } \ No newline at end of file --- 31,558 ---- import org.rubypeople.rdt.core.IRubyScript; import org.rubypeople.rdt.core.RubyModelException; + import org.rubypeople.rdt.internal.corext.template.ruby.RubyContextType; import org.rubypeople.rdt.internal.ui.RubyPlugin; import org.rubypeople.rdt.internal.ui.RubyPluginImages; import org.rubypeople.rdt.internal.ui.text.RubyTextTools; + import org.rubypeople.rdt.internal.ui.text.template.contentassist.RubyTemplateAccess; + import org.rubypeople.rdt.internal.ui.text.template.contentassist.TemplateEngine; + import org.rubypeople.rdt.internal.ui.text.template.contentassist.TemplateProposal; import org.rubypeople.rdt.ui.IWorkingCopyManager; + import org.rubypeople.rdt.ui.text.ruby.IRubyCompletionProposal; ! public class RubyCompletionProcessor extends TemplateCompletionProcessor ! implements IContentAssistProcessor { ! private static String[] keywordProposals; ! protected IContextInformationValidator contextInformationValidator = new RubyContextInformationValidator(); ! private static String[] preDefinedGlobals = { "$!", "$@", "$_", "$.", "$&", ! "$n", "$~", "$=", "$/", "$\\", "$0", "$*", "$$", "$?", "$:" }; ! private static String[] globalContexts = { "error message", ! "position of an error occurrence", "latest read string by `gets'", ! "latest read number of line by interpreter", ! "latest matched string by the regexep.", ! "latest matched string by nth parentheses of regexp.", ! "data for latest matche for regexp", ! "whether or not case-sensitive in string matching", ! "input record separator", "output record separator", ! "the name of the ruby scpript file", ! "command line arguments for the ruby scpript", ! "PID for ruby interpreter", ! "status of the latest executed child process", ! "array of paths that ruby interpreter searches for files" }; ! // FIXME This is an ugly hack, just hard-coding method names ! // FIXME Create a model for Ruby core in our Ruby Model! ! private static String[] KERNEL_METHODS = { "abort", "at_exit", "autoload", ! "binding", "block_given?", "callcc", "caller", "catch", "chomp", ! "chomp!", "chop", "chop!", "eval", "exec", "exit", "exit!", "fail", ! "fork", "format", "gets", "global_variables", "gsub", "gsub!", ! "iterator?", "lambda", "load", "local_variables", "loop", "open", ! "p", "print", "printf", "proc", "putc", "puts", "raise", "rand", ! "readline", "readlines", "require", "scan", "select", ! "set_trace_func", "singleton_method_added", "sleep", "split", ! "sprintf", "srand", "sub", "sub!", "syscall", "system", "test", ! "throw", "trace_var", "trap", "untrace_var" }; ! /** ! * The prefix for the current content assist ! */ ! protected String currentPrefix = null; ! /** ! * Cursor position, counted from the beginning of the document. ! * <P> ! * The first position has index '0'. ! */ ! protected int cursorPosition = -1; ! /** ! * The text viewer. ! */ ! private ITextViewer viewer; ! private IWorkingCopyManager fManager; ! private IEditorPart fEditor; ! private TemplateEngine fRubyTemplateEngine; ! public RubyCompletionProcessor(IEditorPart editor) { ! super(); ! fEditor = editor; ! fManager = RubyPlugin.getDefault().getWorkingCopyManager(); ! TemplateContextType contextType = RubyPlugin.getDefault() ! .getTemplateContextRegistry().getContextType( ! RubyContextType.NAME); ! if (contextType == null) { ! contextType = new RubyContextType(); ! RubyPlugin.getDefault().getTemplateContextRegistry() ! .addContextType(contextType); ! } ! if (contextType != null) ! fRubyTemplateEngine = new TemplateEngine(contextType); ! else ! fRubyTemplateEngine = null; ! } ! public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, ! int documentOffset) { ! this.viewer = viewer; ! ITextSelection selection = (ITextSelection) viewer ! .getSelectionProvider().getSelection(); ! cursorPosition = selection.getOffset() + selection.getLength(); ! ICompletionProposal[] normal = determineRubyElementProposals(viewer, ! documentOffset); ! List templates = determineTemplateProposals(viewer, documentOffset); ! ICompletionProposal[] templateArray = new ICompletionProposal[templates ! .size()]; ! int i = 0; ! for (Iterator iter = templates.iterator(); iter.hasNext(); i++) { ! templateArray[i] = (ICompletionProposal) iter.next(); ! } ! ICompletionProposal[] merged = merge(normal, templateArray); ! ICompletionProposal[] keywords = determineKeywordProposals(viewer, ! documentOffset); ! ICompletionProposal[] mergedTwo = merge(merged, keywords); ! return mergedTwo; ! } ! /** ! * @param arrayOne ! * @param arrayTwo ! * @return ! */ ! private ICompletionProposal[] merge(ICompletionProposal[] arrayOne, ! ICompletionProposal[] arrayTwo) { ! ICompletionProposal[] merged = new ICompletionProposal[arrayOne.length ! + arrayTwo.length]; ! System.arraycopy(arrayOne, 0, merged, 0, arrayOne.length); ! System.arraycopy(arrayTwo, 0, merged, arrayOne.length, arrayTwo.length); ! return merged; ! } ! /** ! * @param viewer ! * @param documentOffset ! * @return ! */ ! private ICompletionProposal[] determineRubyElementProposals( ! ITextViewer viewer, int documentOffset) { ! Collection completionProposals = getDocumentsRubyElements(); ! String prefix = getCurrentPrefix(viewer.getDocument().get(), ! documentOffset); ! // following the JDT convention, if there's no text already entered, ! // then don't suggest imported elements ! if (prefix.length() > 0) { ! // FIXME Add elements from required/loaded files! ! } ! List possibleProposals = new ArrayList(); ! for (Iterator iter = completionProposals.iterator(); iter.hasNext();) { ! String proposal = (String) iter.next(); ! if (proposal.startsWith(prefix)) { ! String message = "{0}"; ! IContextInformation info = new ContextInformation(proposal, ! MessageFormat ! .format(message, new Object[] { proposal })); ! possibleProposals ! .add(new CompletionProposal(proposal.substring(prefix ! .length(), proposal.length()), documentOffset, ! 0, proposal.length() - prefix.length(), null, ! proposal, info, MessageFormat.format( ! "Ruby keyword: {0}", ! new Object[] { proposal }))); ! } ! } ! ICompletionProposal[] result = new ICompletionProposal[possibleProposals ! .size()]; ! possibleProposals.toArray(result); ! return result; ! } ! private Collection addKernelMethods() { ! Collection kernelProposals = new ArrayList(); ! for (int i = 0; i < KERNEL_METHODS.length; i++) { ! kernelProposals.add(KERNEL_METHODS[i]); ! } ! return kernelProposals; ! } ! /* ! * (non-Javadoc) ! * ! * @see org.eclipse.jface.text.templates.TemplateCompletionProcessor#getImage(org.eclipse.jface.text.templates.Template) ! */ ! protected Image getImage(Template template) { ! return RubyPluginImages.get(RubyPluginImages.IMG_OBJS_TEMPLATE); ! } ! /* ! * (non-Javadoc) ! * ! * @see org.eclipse.jface.text.templates.TemplateCompletionProcessor#getContextType(org.eclipse.jface.text.ITextViewer, ! * org.eclipse.jface.text.IRegion) ! */ ! protected TemplateContextType getContextType(ITextViewer textViewer, ! IRegion region) { ! return RubyTemplateAccess.getDefault().getContextTypeRegistry() ! .getContextType(RubyContextType.NAME); ! } ! /** ! * Creates the context that is passed to the completion proposal computers. ! * ! * @param viewer ! * the viewer that content assist is invoked on ! * @param offset ! * the content assist offset ! * @return the context to be passed to the computers ! */ ! protected TextContentAssistInvocationContext createContext( ! ITextViewer viewer, int offset) { ! return new TextContentAssistInvocationContext(viewer, offset); ! } ! /** ! * @return ! */ ! private List determineTemplateProposals(ITextViewer refViewer, ! int documentOffset) { ! TemplateEngine engine = fRubyTemplateEngine; ! TextContentAssistInvocationContext context = createContext(viewer, ! documentOffset); ! if (engine != null) { ! IRubyScript unit = fManager ! .getWorkingCopy(fEditor.getEditorInput()); ! if (unit == null) ! return Collections.EMPTY_LIST; ! engine.reset(); ! engine.complete(context.getViewer(), context.getInvocationOffset(), ! unit); ! TemplateProposal[] templateProposals = engine.getResults(); ! List result = new ArrayList(Arrays.asList(templateProposals)); ! IRubyCompletionProposal[] keyWordResults = getKeywordProposals(documentOffset); ! if (keyWordResults.length > 0) { ! List removals = new ArrayList(); ! // update relevance of template proposals that match with a ! // keyword ! // give those templates slightly more relevance than the keyword ! // to ! // sort them first ! // remove keyword templates that don't have an equivalent ! // keyword proposal ! if (keyWordResults.length > 0) { ! outer: for (int k = 0; k < templateProposals.length; k++) { ! TemplateProposal curr = templateProposals[k]; ! String name = curr.getTemplate().getName(); ! for (int i = 0; i < keyWordResults.length; i++) { ! String keyword = keyWordResults[i] ! .getDisplayString(); ! if (name.startsWith(keyword)) { ! curr.setRelevance(keyWordResults[i] ! .getRelevance() + 1); ! continue outer; ! } ! } ! if (isKeyword(name)) ! removals.add(curr); ! } ! } ! result.removeAll(removals); ! } ! return result; ! } ! return Collections.EMPTY_LIST; ! } ! private IRubyCompletionProposal[] getKeywordProposals(int documentOffset) { ! List keywords = getKeywords(); ! List fKeywords = new ArrayList(); ! for (Iterator iter = keywords.iterator(); iter.hasNext();) { ! String keyword = (String) iter.next(); ! String prefix = getCurrentPrefix(viewer.getDocument().get(), ! documentOffset); ! if (prefix.length() >= keyword.length()) ! continue; ! fKeywords.add(createKeywordProposal(keyword, prefix, documentOffset)); ! } ! return (IRubyCompletionProposal[]) fKeywords ! .toArray(new RubyCompletionProposal[fKeywords.size()]); ! } ! private IRubyCompletionProposal createKeywordProposal(String keyword, ! String prefix, int documentOffset) { ! String completion = keyword ! .substring(prefix.length(), keyword.length()); ! return new RubyCompletionProposal(completion, documentOffset, ! completion.length(), RubyPluginImages ! .get(RubyPluginImages.IMG_OBJS_TEMPLATE), keyword, 0); ! } ! private List getKeywords() { ! List list = new ArrayList(); ! String[] keywords = RubyTextTools.getKeyWords(); ! for (int i = 0; i < keywords.length; i++) { ! list.add(keywords[i]); ! } ! return list; ! } ! private boolean isKeyword(String name) { ! return getKeywords().contains(name); ! } ! /** ! * @param proposal ! * @return ! */ ! private String getContext(String proposal) { ! for (int i = 0; i < preDefinedGlobals.length; i++) { ! if (proposal.equals(preDefinedGlobals[i])) ! return globalContexts[i]; ! } ! return ""; ! } ! /** ! * @param proposal ! * @return ! */ ! private boolean isPredefinedGlobal(String proposal) { ! for (int i = 0; i < preDefinedGlobals.length; i++) { ! if (proposal.equals(preDefinedGlobals[i])) ! return true; ! } ! return false; ! } ! /** ! * Gets all the distinct elements in the current RubyScript ! * ! * @return a List of the names of all the elements in the current RubyScript ! */ ! private Collection getDocumentsRubyElements() { ! IRubyScript script = fManager.getWorkingCopy(fEditor.getEditorInput()); ! // FIXME Get only the elements in the current scope! ! Collection elements = getElements(script); ! IRubyProject project = script.getRubyProject(); ! // Add all the classes and modules in the project ! elements.addAll(addClassesAndModulesInProject(project)); ! // Add all the classes and modules in referenced projects ! for (Iterator iter = project.getReferencedProjects().iterator(); iter ! .hasNext();) { ! elements.addAll(addClassesAndModulesInProject(((IRubyProject) iter ! .next()))); ! } ! // TODO Add all the methods defined in included modules for the class ! // TODO Add all the methods defined in superclasses for the class/module ! // always add Kernel methods ! elements.addAll(addKernelMethods()); ! return elements; ! } ! private Collection addClassesAndModulesInProject(IRubyProject project) { ! return getElementsOfType(project, new int[] { IRubyElement.TYPE }); ! } ! private Collection getElementsOfType(IParent element, int[] types) { ! Collection suggestions = new ArrayList(); ! try { ! IRubyElement[] elements = element.getChildren(); ! if (elements == null) ! return suggestions; ! for (int x = 0; x < elements.length; x++) { ! IRubyElement child = elements[x]; ! for (int i = 0; i < types.length; i++) { ! if (child.getElementType() == types[i]) { ! suggestions.add(child.getElementName()); ! break; ! } ! } ! if (child instanceof IParent) ! suggestions ! .addAll(getElementsOfType((IParent) child, types)); ! } ! } catch (RubyModelException e) { ! e.printStackTrace(); ! } ! return suggestions; ! } ! /** ! * @param script ! * @return ! */ ! private Collection getElements(IParent element) { ! return getElementsOfType(element, new int[] { IRubyElement.TYPE, ! IRubyElement.METHOD, IRubyElement.GLOBAL, ! IRubyElement.CONSTANT, IRubyElement.CLASS_VAR, ! IRubyElement.INSTANCE_VAR }); ! } ! private ICompletionProposal[] determineKeywordProposals(ITextViewer viewer, ! int documentOffset) { ! initKeywordProposals(); ! ! String prefix = getCurrentPrefix(viewer.getDocument().get(), ! documentOffset); ! // following the JDT convention, if there's no text already entered, ! // then don't suggest keywords ! if (prefix.length() < 1) { ! return new ICompletionProposal[0]; ! } ! List completionProposals = Arrays.asList(keywordProposals); ! ! // FIXME Refactor to combine the copied code in ! // determineRubyElementProposals ! List possibleProposals = new ArrayList(); ! for (int i = 0; i < completionProposals.size(); i++) { ! String proposal = (String) completionProposals.get(i); ! if (proposal.startsWith(prefix)) { ! String message; ! if (isPredefinedGlobal(proposal)) { ! message = "{0} " + getContext(proposal); ! } else { ! message = "{0}"; ! } ! IContextInformation info = new ContextInformation(proposal, ! MessageFormat ! .format(message, new Object[] { proposal })); ! possibleProposals ! .add(new CompletionProposal(proposal.substring(prefix ! .length(), proposal.length()), documentOffset, ! 0, proposal.length() - prefix.length(), null, ! proposal, info, MessageFormat.format( ! "Ruby keyword: {0}", ! new Object[] { proposal }))); ! } ! } ! ICompletionProposal[] result = new ICompletionProposal[possibleProposals ! .size()]; ! possibleProposals.toArray(result); ! return result; ! } ! ! /** ! * ! */ ! private void initKeywordProposals() { ! if (keywordProposals == null) { ! String[] keywords = RubyTextTools.getKeyWords(); ! keywordProposals = new String[keywords.length ! + preDefinedGlobals.length]; ! System.arraycopy(keywords, 0, keywordProposals, 0, keywords.length); ! System.arraycopy(preDefinedGlobals, 0, keywordProposals, ! keywords.length, preDefinedGlobals.length); ! } ! } ! ! protected String getCurrentPrefix(String documentString, int documentOffset) { ! int tokenLength = 0; ! while ((documentOffset - tokenLength > 0) ! && !Character.isWhitespace(documentString.charAt(documentOffset ! - tokenLength - 1))) ! tokenLength++; ! return documentString.substring((documentOffset - tokenLength), ! documentOffset); ! } ! ! /* ! * (non-Javadoc) ! * ! * @see org.eclipse.jface.text.templates.TemplateCompletionProcessor#getTemplates(java.lang.String) ! */ ! protected Template[] getTemplates(String contextTypeId) { ! return RubyTemplateAccess.getDefault().getTemplateStore() ! .getTemplates(); ! } ! ! public IContextInformation[] computeContextInformation(ITextViewer viewer, ! int documentOffset) { ! return null; ! } ! ! public char[] getCompletionProposalAutoActivationCharacters() { ! return null; ! } ! ! public char[] getContextInformationAutoActivationCharacters() { ! return new char[] { '#' }; ! } ! ! public IContextInformationValidator getContextInformationValidator() { ! return contextInformationValidator; ! } ! ! public String getErrorMessage() { ! return null; ! } ! ! protected class RubyContextInformationValidator implements ! IContextInformationValidator, IContextInformationPresenter { ! ! protected int installDocumentPosition; ! ! /** ! * @see org.eclipse.jface.text.contentassist.IContextInformationPresenter#install(IContextInformation, ! * ITextViewer, int) ! */ ! public void install(IContextInformation info, ITextViewer viewer, ! int documentPosition) { ! installDocumentPosition = documentPosition; ! } ! ! /** ! * @see org.eclipse.jface.text.contentassist.IContextInformationValidator#isContextInformationValid(int) ! */ ! public boolean isContextInformationValid(int documentPosition) { ! return Math.abs(installDocumentPosition - documentPosition) < 1; ! } ! ! /** ! * @see org.eclipse.jface.text.contentassist.IContextInformationPresenter#updatePresentation(int, ! * TextPresentation) ! */ ! public boolean updatePresentation(int documentPosition, ! TextPresentation presentation) { ! return false; ! } ! } } \ No newline at end of file |
|
From: Christopher W. <caw...@us...> - 2006-02-18 16:53:55
|
Update of /cvsroot/rubyeclipse/org.rubypeople.rdt.ui In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv28822 Modified Files: plugin.xml Log Message: overhaul our completion proposal/template code. Now we will apply formatting to templates when inserted! Plus we're closer to the way JDT does things. We still can't use the actual code formatter on the templates (because our old one does a massive replace edit which messes up variables like the cursor placement). The end result is that users should create templates with somewhat proper formatting initially. Index: plugin.xml =================================================================== RCS file: /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/plugin.xml,v retrieving revision 1.72 retrieving revision 1.73 diff -C2 -d -r1.72 -r1.73 *** plugin.xml 10 Feb 2006 20:17:20 -0000 1.72 --- plugin.xml 18 Feb 2006 16:53:51 -0000 1.73 *************** *** 37,41 **** name="%PreferencePage.rdtTemplatePreferences" category="org.rubypeople.rdt.ui.preferences.PreferencePageRubyBase" ! class="org.rubypeople.rdt.internal.ui.rubyeditor.templates.RubyTemplatePreferencePage" id="org.rubypeople.rdt.ui.TemplatesPreferencePage"> </page> --- 37,41 ---- name="%PreferencePage.rdtTemplatePreferences" category="org.rubypeople.rdt.ui.preferences.PreferencePageRubyBase" ! class="org.rubypeople.rdt.internal.ui.preferences.RubyTemplatePreferencePage" id="org.rubypeople.rdt.ui.TemplatesPreferencePage"> </page> *************** *** 221,224 **** --- 221,231 ---- sequence="M1+SPACE"> </key> + <key + commandId="org.rubypeople.rdt.ui.edit.text.ruby.content.assist.proposals" + contextId="org.rubypeople.rdt.ui.rubyEditorScope" + schemeId="org.eclipse.ui.defaultAcceleratorConfiguration" + sequence="CTRL+SPACE" + platform="carbon"> + </key> </extension> <extension point="org.eclipse.ui.commands"> *************** *** 462,488 **** </filter> </extension> <extension point="org.eclipse.ui.editors.templates"> <contextType name="%rubyFile.contextType.name" ! class="org.rubypeople.rdt.internal.ui.rubyeditor.templates.RubyFileContextType" ! id="org.rubypeople.rdt.ui.templateContextType.rubyFile"> </contextType> - <resolver - name="%rdt.resolvers.src" - type="src" - icon="templates/resolver.gif" - description="%rdt.resolvers.src.description" - contextTypeId="org.rubypeople.rdt.ui.templateContextType.XML" - class="org.rubypeople.rdt.internal.ui.rubyeditor.templates.RubyVariableResolver"> - </resolver> - <resolver - name="%rdt.resolvers.dst" - type="dst" - icon="templates/resolver.gif" - description="%rdt.resolvers.dst.description" - contextTypeId="org.rubypeople.rdt.ui.templateContextType.XML" - class="org.rubypeople.rdt.internal.ui.rubyeditor.templates.RubyVariableResolver"> - </resolver> <include file="templates/rdt.xml" --- 469,482 ---- </filter> </extension> + <!-- =========================================================================== --> + <!-- Templates --> + <!-- =========================================================================== --> <extension point="org.eclipse.ui.editors.templates"> <contextType name="%rubyFile.contextType.name" ! class="org.rubypeople.rdt.internal.corext.template.ruby.RubyContextType" ! id="ruby"> </contextType> <include file="templates/rdt.xml" |
|
From: Christopher W. <caw...@us...> - 2006-02-18 16:53:54
|
Update of /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/META-INF In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv28822/META-INF Modified Files: MANIFEST.MF Log Message: overhaul our completion proposal/template code. Now we will apply formatting to templates when inserted! Plus we're closer to the way JDT does things. We still can't use the actual code formatter on the templates (because our old one does a massive replace edit which messes up variables like the cursor placement). The end result is that users should create templates with somewhat proper formatting initially. Index: MANIFEST.MF =================================================================== RCS file: /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/META-INF/MANIFEST.MF,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** MANIFEST.MF 10 Feb 2006 20:15:29 -0000 1.8 --- MANIFEST.MF 18 Feb 2006 16:53:51 -0000 1.9 *************** *** 18,22 **** org.rubypeople.rdt.internal.ui.resourcesview, org.rubypeople.rdt.internal.ui.rubyeditor, - org.rubypeople.rdt.internal.ui.rubyeditor.templates, org.rubypeople.rdt.internal.ui.search, org.rubypeople.rdt.internal.ui.symbols, --- 18,21 ---- |
|
From: Christopher W. <caw...@us...> - 2006-02-18 16:53:54
|
Update of /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv28822/src/org/rubypeople/rdt/ui Modified Files: PreferenceConstants.java Log Message: overhaul our completion proposal/template code. Now we will apply formatting to templates when inserted! Plus we're closer to the way JDT does things. We still can't use the actual code formatter on the templates (because our old one does a massive replace edit which messes up variables like the cursor placement). The end result is that users should create templates with somewhat proper formatting initially. Index: PreferenceConstants.java =================================================================== RCS file: /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/PreferenceConstants.java,v retrieving revision 1.11 retrieving revision 1.12 diff -C2 -d -r1.11 -r1.12 *** PreferenceConstants.java 10 Feb 2006 20:14:52 -0000 1.11 --- PreferenceConstants.java 18 Feb 2006 16:53:51 -0000 1.12 *************** *** 18,23 **** public static final String FORMAT_INDENTATION = "formatIndentation"; //$NON-NLS-1$ public static final String FORMAT_USE_TAB = "formatUseTab"; //$NON-NLS-1$ ! // TODO Finish implementing this option! ! public static final String TEMPLATES_USE_CODEFORMATTER = "templatesUSeCodeFormatter"; private final static String DEFAULT_RDOC_CMD = "rdoc"; //$NON-NLS-1$ --- 18,22 ---- public static final String FORMAT_INDENTATION = "formatIndentation"; //$NON-NLS-1$ public static final String FORMAT_USE_TAB = "formatUseTab"; //$NON-NLS-1$ ! public static final String TEMPLATES_USE_CODEFORMATTER = "templatesUseCodeFormatter"; //$NON-NLS-1$ private final static String DEFAULT_RDOC_CMD = "rdoc"; //$NON-NLS-1$ *************** *** 228,231 **** --- 227,234 ---- store.setDefault(PreferenceConstants.EDITOR_SHOW_SEGMENTS, false); + // FIXME We can't enabling using code formatter yet, because it breaks on formatting templates (when inserting via content assist) + // FIXME Uncomment when we have an AST based formatter which spits out TextEdits (rather than one huge replace) + // store.setDefault(PreferenceConstants.TEMPLATES_USE_CODEFORMATTER, true); + store.setDefault(PreferenceConstants.FORMATTER_PROFILE, ProfileManager.DEFAULT_PROFILE); |
|
From: Christopher W. <caw...@us...> - 2006-02-18 16:53:54
|
Update of /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv28822/src/org/rubypeople/rdt/internal/ui Modified Files: RubyPluginImages.java RubyPlugin.java Log Message: overhaul our completion proposal/template code. Now we will apply formatting to templates when inserted! Plus we're closer to the way JDT does things. We still can't use the actual code formatter on the templates (because our old one does a massive replace edit which messes up variables like the cursor placement). The end result is that users should create templates with somewhat proper formatting initially. Index: RubyPluginImages.java =================================================================== RCS file: /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/RubyPluginImages.java,v retrieving revision 1.13 retrieving revision 1.14 diff -C2 -d -r1.13 -r1.14 *** RubyPluginImages.java 10 Feb 2006 20:14:19 -0000 1.13 --- RubyPluginImages.java 18 Feb 2006 16:53:50 -0000 1.14 *************** *** 56,60 **** private static final String IMG_CTOOLS_RUBY_IMPORT_CONTAINER = NAME_PREFIX + "imp_c.gif"; private static final String IMG_CTOOLS_RUBY_IMPORT = NAME_PREFIX + "imp_obj.gif"; ! public static final String IMG_TEMPLATE_PROPOSAL = NAME_PREFIX + "template_obj.gif"; private static final String IMG_CTOOLS_RUBY_LOCAL_VAR = NAME_PREFIX + "localvariable_obj.gif"; public static final String IMG_CTOOLS_RUBY_PAGE = NAME_PREFIX + "ruby_page.gif"; --- 56,60 ---- private static final String IMG_CTOOLS_RUBY_IMPORT_CONTAINER = NAME_PREFIX + "imp_c.gif"; private static final String IMG_CTOOLS_RUBY_IMPORT = NAME_PREFIX + "imp_obj.gif"; ! public static final String IMG_OBJS_TEMPLATE = NAME_PREFIX + "template_obj.gif"; private static final String IMG_CTOOLS_RUBY_LOCAL_VAR = NAME_PREFIX + "localvariable_obj.gif"; public static final String IMG_CTOOLS_RUBY_PAGE = NAME_PREFIX + "ruby_page.gif"; *************** *** 128,132 **** public static final ImageDescriptor DESC_OBJS_UNKNOWN= createManaged(T_OBJ, IMG_OBJS_UNKNOWN); ! static { --- 128,132 ---- public static final ImageDescriptor DESC_OBJS_UNKNOWN= createManaged(T_OBJ, IMG_OBJS_UNKNOWN); ! static { *************** *** 136,140 **** createManaged(T_OBJ, IMG_OBJS_WARNING); createManaged(T_OBJ, IMG_OBJS_INFO); ! createManaged(T_OBJ, IMG_TEMPLATE_PROPOSAL); createManaged(T_CTOOL, IMG_CTOOLS_RUBY_IMPORT_CONTAINER); createManaged(T_CTOOL, IMG_CTOOLS_RUBY_IMPORT); --- 136,140 ---- createManaged(T_OBJ, IMG_OBJS_WARNING); createManaged(T_OBJ, IMG_OBJS_INFO); ! createManaged(T_OBJ, IMG_OBJS_TEMPLATE); createManaged(T_CTOOL, IMG_CTOOLS_RUBY_IMPORT_CONTAINER); createManaged(T_CTOOL, IMG_CTOOLS_RUBY_IMPORT); Index: RubyPlugin.java =================================================================== RCS file: /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/RubyPlugin.java,v retrieving revision 1.23 retrieving revision 1.24 diff -C2 -d -r1.23 -r1.24 *** RubyPlugin.java 10 Feb 2006 20:14:19 -0000 1.23 --- RubyPlugin.java 18 Feb 2006 16:53:50 -0000 1.24 *************** *** 55,59 **** import org.rubypeople.rdt.internal.ui.rubyeditor.RubyDocumentProvider; import org.rubypeople.rdt.internal.ui.rubyeditor.WorkingCopyManager; - import org.rubypeople.rdt.internal.ui.rubyeditor.templates.RubyTemplateAccess; import org.rubypeople.rdt.internal.ui.symbols.BlockingSymbolFinder; import org.rubypeople.rdt.internal.ui.text.IRubyColorConstants; --- 55,58 ---- *************** *** 61,64 **** --- 60,64 ---- import org.rubypeople.rdt.internal.ui.text.RubyTextTools; import org.rubypeople.rdt.internal.ui.text.folding.RubyFoldingStructureProviderRegistry; + import org.rubypeople.rdt.internal.ui.text.template.contentassist.RubyTemplateAccess; import org.rubypeople.rdt.ui.IWorkingCopyManager; import org.rubypeople.rdt.ui.PreferenceConstants; |
|
From: Christopher W. <caw...@us...> - 2006-02-18 16:53:54
|
Update of /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/templates In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv28822/src/org/rubypeople/rdt/internal/ui/rubyeditor/templates Removed Files: RubyFileContextType.java RubyContext.java RubyVariableResolver.java RubyTemplateAccess.java RubyTemplateInformationControlCreator.java RubyTemplatePreferencePage.java RubyTemplateVariableTextHover.java RubyTemplateProposal.java RubySourceViewerInformationControl.java Log Message: overhaul our completion proposal/template code. Now we will apply formatting to templates when inserted! Plus we're closer to the way JDT does things. We still can't use the actual code formatter on the templates (because our old one does a massive replace edit which messes up variables like the cursor placement). The end result is that users should create templates with somewhat proper formatting initially. --- RubyTemplateAccess.java DELETED --- --- RubyFileContextType.java DELETED --- --- RubyTemplateVariableTextHover.java DELETED --- --- RubyVariableResolver.java DELETED --- --- RubyContext.java DELETED --- --- RubyTemplatePreferencePage.java DELETED --- --- RubyTemplateProposal.java DELETED --- --- RubySourceViewerInformationControl.java DELETED --- --- RubyTemplateInformationControlCreator.java DELETED --- |
|
From: Christopher W. <caw...@us...> - 2006-02-18 16:53:53
|
Update of /cvsroot/rubyeclipse/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/template/contentassist In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv28822/src/org/rubypeople/rdt/internal/ui/text/template/contentassist Added Files: VariablePosition.java TemplateProposal.java TemplateEngine.java TemplateContentAssistMessages.java MultiVariableGuess.java RubyTemplateVariableTextHover.java RubyTemplateAccess.java PositionBasedCompletionProposal.java MultiVariable.java TemplateInformationControlCreator.java TemplateContentAssistMessages.properties Log Message: overhaul our completion proposal/template code. Now we will apply formatting to templates when inserted! Plus we're closer to the way JDT does things. We still can't use the actual code formatter on the templates (because our old one does a massive replace edit which messes up variables like the cursor placement). The end result is that users should create templates with somewhat proper formatting initially. --- NEW FILE: TemplateContentAssistMessages.java --- /******************************************************************************* * Copyright (c) 2000, 2005 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.rubypeople.rdt.internal.ui.text.template.contentassist; import org.eclipse.osgi.util.NLS; /** * Helper class to get NLSed messages. */ final class TemplateContentAssistMessages extends NLS { private static final String BUNDLE_NAME= TemplateContentAssistMessages.class.getName(); private TemplateContentAssistMessages() { // Do not instantiate } public static String TemplateProposal_displayString; public static String TemplateEvaluator_error_title; static { NLS.initializeMessages(BUNDLE_NAME, TemplateContentAssistMessages.class); } } --- NEW FILE: TemplateInformationControlCreator.java --- /******************************************************************************* * Copyright (c) 2000, 2005 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.rubypeople.rdt.internal.ui.text.template.contentassist; import org.eclipse.jface.text.IInformationControl; import org.eclipse.jface.text.IInformationControlCreator; import org.eclipse.jface.text.IInformationControlCreatorExtension; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.widgets.Shell; import org.rubypeople.rdt.internal.ui.text.ruby.hover.SourceViewerInformationControl; final public class TemplateInformationControlCreator implements IInformationControlCreator, IInformationControlCreatorExtension { private SourceViewerInformationControl fControl; public TemplateInformationControlCreator() { } /* * @see org.eclipse.jface.text.IInformationControlCreator#createInformationControl(org.eclipse.swt.widgets.Shell) */ public IInformationControl createInformationControl(Shell parent) { fControl= new SourceViewerInformationControl(parent); fControl.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { fControl= null; } }); return fControl; } /* * @see org.eclipse.jface.text.IInformationControlCreatorExtension#canReuse(org.eclipse.jface.text.IInformationControl) */ public boolean canReuse(IInformationControl control) { return fControl == control && fControl != null; } /* * @see org.eclipse.jface.text.IInformationControlCreatorExtension#canReplace(org.eclipse.jface.text.IInformationControlCreator) */ public boolean canReplace(IInformationControlCreator creator) { return (creator != null && getClass() == creator.getClass()); } } --- NEW FILE: RubyTemplateAccess.java --- /******************************************************************************* * Copyright (c) 2000, 2004 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/cpl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.rubypeople.rdt.internal.ui.text.template.contentassist; import java.io.IOException; import java.util.ArrayList; import java.util.List; 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.Platform; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.text.templates.ContextTypeRegistry; import org.eclipse.jface.text.templates.persistence.TemplatePersistenceData; import org.eclipse.jface.text.templates.persistence.TemplateStore; import org.eclipse.ui.editors.text.templates.ContributionContextTypeRegistry; import org.eclipse.ui.editors.text.templates.ContributionTemplateStore; import org.rubypeople.rdt.internal.corext.template.ruby.RubyContextType; import org.rubypeople.rdt.internal.ui.RubyPlugin; import org.rubypeople.rdt.ui.extensions.IRubyTemplateProvider; public class RubyTemplateAccess { /** Key to store custom templates. */ private static final String CUSTOM_TEMPLATES_KEY= "org.rubypeople.rdt.ui.customtemplates"; //$NON-NLS-1$ /** The shared instance. */ private static RubyTemplateAccess fgInstance; /** The template store. */ private TemplateStore fStore; /** The context type registry. */ private ContributionContextTypeRegistry fContextTypeRegistry; private RubyTemplateAccess() {} /** * Returns the shared instance. * * @return the shared instance */ public static RubyTemplateAccess getDefault() { if (fgInstance == null) { fgInstance= new RubyTemplateAccess(); } return fgInstance; } /** * Returns this plug-in's template store. * * @return the template store of this plug-in instance */ public TemplateStore getTemplateStore() { if (fStore == null) { fStore= new ContributionTemplateStore(getContextTypeRegistry(),RubyPlugin.getDefault().getPreferenceStore(), CUSTOM_TEMPLATES_KEY); try { fStore.load(); } catch (IOException e) { RubyPlugin.log(e); } // Load extension templates TemplatePersistenceData[] tempData = getExtensionTemplateData(); if(tempData != null) { for(int i = 0; i < tempData.length; i++) { fStore.add(tempData[i]); } } } return fStore; } /** * Finds all extensions to the rubyTemplateProvider extension point and return their template data. * * @return an array of TemplatePersistenceData */ private TemplatePersistenceData[] getExtensionTemplateData() { List extensions = new ArrayList(); IExtensionRegistry reg = Platform.getExtensionRegistry(); IExtensionPoint[] points = reg.getExtensionPoints(RubyPlugin.PLUGIN_ID); IExtensionPoint point = null; // Search the extension registry for the rubyTemplateProvider extension point if(points != null){ for (int i = 0; i < points.length; i++) { IExtensionPoint currentPoint = points[i]; if(currentPoint.getUniqueIdentifier().endsWith("rubyTemplateProvider")){ point = currentPoint; break; } } // Find all extensions of the point if(point != null){ IExtension[] exts = point.getExtensions(); IRubyTemplateProvider prov = null; // Get the implementing class of the extension for (int i = 0; i < exts.length; i++) { IConfigurationElement[] elem = exts[i].getConfigurationElements(); String attrs[] = elem[0].getAttributeNames(); try { Object tempProv = elem[0].createExecutableExtension("class"); if (tempProv instanceof IRubyTemplateProvider) { prov = (IRubyTemplateProvider) tempProv; extensions.add(prov); } } catch (CoreException e) { RubyPlugin.log(e); } } } } // Get the template data from the extensions if(extensions.size() > 0){ for(int i=0; i< extensions.size(); i++){ IRubyTemplateProvider currentProvider = (IRubyTemplateProvider) extensions.get(i); TemplatePersistenceData[] templates = currentProvider.getTemplateData(); if(templates != null){ return templates; } } } return null; } /** * Returns this plug-in's context type registry. * * @return the context type registry for this plug-in instance */ public ContextTypeRegistry getContextTypeRegistry() { if (fContextTypeRegistry == null) { // create and configure the contexts available in the template editor fContextTypeRegistry= new ContributionContextTypeRegistry(); fContextTypeRegistry.addContextType(new RubyContextType()); } return fContextTypeRegistry; } public IPreferenceStore getPreferenceStore() { return RubyPlugin.getDefault().getPreferenceStore(); } public void savePluginPreferences() { RubyPlugin.getDefault().savePluginPreferences(); } } --- NEW FILE: MultiVariable.java --- /******************************************************************************* * Copyright (c) 2000, 2005 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.rubypeople.rdt.internal.ui.text.template.contentassist; import java.util.HashMap; import java.util.Map; import org.eclipse.jface.text.Assert; import org.eclipse.jface.text.templates.TemplateVariable; /** * */ public class MultiVariable extends TemplateVariable { private final Map fValueMap= new HashMap(); private Object fSet; private Object fDefaultKey= null; public MultiVariable(String type, String defaultValue, int[] offsets) { super(type, defaultValue, offsets); fValueMap.put(fDefaultKey, new String[] { defaultValue }); fSet= getDefaultValue(); } /** * Sets the values of this variable under a specific set. * * @param set the set identifier for which the values are valid * @param values the possible values of this variable */ public void setValues(Object set, String[] values) { Assert.isNotNull(set); Assert.isTrue(values.length > 0); fValueMap.put(set, values); if (fDefaultKey == null) { fDefaultKey= set; fSet= getDefaultValue(); } } /* * @see org.eclipse.jface.text.templates.TemplateVariable#setValues(java.lang.String[]) */ public void setValues(String[] values) { if (fValueMap != null) { Assert.isNotNull(values); Assert.isTrue(values.length > 0); fValueMap.put(fDefaultKey, values); fSet= getDefaultValue(); } } /* * @see org.eclipse.jface.text.templates.TemplateVariable#getValues() */ public String[] getValues() { return (String[]) fValueMap.get(fDefaultKey); } /** * Returns the choices for the set identified by <code>set</code>. * * @param set the set identifier * @return the choices for this variable and the given set, or * <code>null</code> if the set is not defined. */ public String[] getValues(Object set) { return (String[]) fValueMap.get(set); } /** * @return */ public Object getSet() { return fSet; } public void setSet(Object set) { fSet= set; } } --- NEW FILE: RubyTemplateVariableTextHover.java --- /******************************************************************************* * Copyright (c) 2000, 2004 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/cpl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.rubypeople.rdt.internal.ui.text.template.contentassist; import java.util.Iterator; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextHover; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.Region; import org.eclipse.jface.text.templates.TemplateContextType; import org.eclipse.jface.text.templates.TemplateVariableResolver; import org.rubypeople.rdt.internal.corext.template.ruby.RubyContextType; public class RubyTemplateVariableTextHover implements ITextHover { public RubyTemplateVariableTextHover() { } /* (non-Javadoc) * @see org.eclipse.jface.text.ITextHover#getHoverInfo(org.eclipse.jface.text.ITextViewer, org.eclipse.jface.text.IRegion) */ public String getHoverInfo(ITextViewer textViewer, IRegion subject) { try { IDocument doc= textViewer.getDocument(); int offset= subject.getOffset(); if (offset >= 2 && "${".equals(doc.get(offset-2, 2))) { //$NON-NLS-1$ String varName= doc.get(offset, subject.getLength()); TemplateContextType contextType= RubyTemplateAccess.getDefault().getContextTypeRegistry().getContextType(RubyContextType.NAME); if (contextType != null) { Iterator iter= contextType.resolvers(); while (iter.hasNext()) { TemplateVariableResolver var= (TemplateVariableResolver) iter.next(); if (varName.equals(var.getType())) { return var.getDescription(); } } } } } catch (BadLocationException e) { } return null; } /* (non-Javadoc) * @see org.eclipse.jface.text.ITextHover#getHoverRegion(org.eclipse.jface.text.ITextViewer, int) */ public IRegion getHoverRegion(ITextViewer textViewer, int offset) { if (textViewer != null) { // FIXME Rewrite this! I just stole it from Ant! IDocument document= textViewer.getDocument(); int start= -1; int end= -1; try { int pos= offset; char c; while (pos >= 0) { c= document.getChar(pos); if (c != '.' && c != '-' && c != '/' && c != '\\' && !Character.isJavaIdentifierPart(c)) break; --pos; } start= pos; pos= offset; int length= document.getLength(); while (pos < length) { c= document.getChar(pos); if (c != '.' && c != '-' && !Character.isJavaIdentifierPart(c)) break; ++pos; } end= pos; } catch (BadLocationException x) { } if (start > -1 && end > -1) { if (start == offset && end == offset) return new Region(offset, 0); else if (start == offset) return new Region(start, end - start); else return new Region(start + 1, end - start - 1); } return null; } return null; } } --- NEW FILE: TemplateEngine.java --- /******************************************************************************* * Copyright (c) 2000, 2005 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.rubypeople.rdt.internal.ui.text.template.contentassist; import java.util.ArrayList; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.Region; import org.eclipse.jface.text.templates.GlobalTemplateVariables; import org.eclipse.jface.text.templates.Template; import org.eclipse.jface.text.templates.TemplateContextType; import org.eclipse.swt.graphics.Point; import org.rubypeople.rdt.core.IRubyScript; import org.rubypeople.rdt.internal.corext.Assert; import org.rubypeople.rdt.internal.corext.template.ruby.RubyScriptContextType; import org.rubypeople.rdt.internal.corext.template.ruby.RubyScriptContext; import org.rubypeople.rdt.internal.ui.RubyPlugin; import org.rubypeople.rdt.internal.ui.RubyPluginImages; public class TemplateEngine { private static final String $_LINE_SELECTION= "${" + GlobalTemplateVariables.LineSelection.NAME + "}"; //$NON-NLS-1$ //$NON-NLS-2$ private static final String $_WORD_SELECTION= "${" + GlobalTemplateVariables.WordSelection.NAME + "}"; //$NON-NLS-1$ //$NON-NLS-2$ /** The context type. */ private TemplateContextType fContextType; /** The result proposals. */ private ArrayList fProposals= new ArrayList(); /** * Creates the template engine for a particular context type. * See <code>TemplateContext</code> for supported context types. */ public TemplateEngine(TemplateContextType contextType) { Assert.isNotNull(contextType); fContextType= contextType; } /** * Empties the collector. */ public void reset() { fProposals.clear(); } /** * Returns the array of matching templates. */ public TemplateProposal[] getResults() { return (TemplateProposal[]) fProposals.toArray(new TemplateProposal[fProposals.size()]); } /** * Inspects the context of the compilation unit around <code>completionPosition</code> * and feeds the collector with proposals. * @param viewer the text viewer * @param completionPosition the context position in the document of the text viewer * @param compilationUnit the compilation unit (may be <code>null</code>) */ public void complete(ITextViewer viewer, int completionPosition, IRubyScript compilationUnit) { IDocument document= viewer.getDocument(); if (!(fContextType instanceof RubyScriptContextType)) return; Point selection= viewer.getSelectedRange(); // remember selected text String selectedText= null; if (selection.y != 0) { try { selectedText= document.get(selection.x, selection.y); } catch (BadLocationException e) {} } RubyScriptContext context= ((RubyScriptContextType) fContextType).createContext(document, completionPosition, selection.y, compilationUnit); context.setVariable("selection", selectedText); //$NON-NLS-1$ int start= context.getStart(); int end= context.getEnd(); IRegion region= new Region(start, end - start); Template[] templates= RubyPlugin.getDefault().getTemplateStore().getTemplates(); if (selection.y == 0) { for (int i= 0; i != templates.length; i++) if (context.canEvaluate(templates[i])) fProposals.add(new TemplateProposal(templates[i], context, region, RubyPluginImages.get(RubyPluginImages.IMG_OBJS_TEMPLATE))); } else { if (context.getKey().length() == 0) context.setForceEvaluation(true); boolean multipleLinesSelected= areMultipleLinesSelected(viewer); for (int i= 0; i != templates.length; i++) { Template template= templates[i]; if (context.canEvaluate(template) && template.getContextTypeId().equals(context.getContextType().getId()) && (!multipleLinesSelected && template.getPattern().indexOf($_WORD_SELECTION) != -1 || (multipleLinesSelected && template.getPattern().indexOf($_LINE_SELECTION) != -1))) { fProposals.add(new TemplateProposal(templates[i], context, region, RubyPluginImages.get(RubyPluginImages.IMG_OBJS_TEMPLATE))); } } } } /** * Returns <code>true</code> if one line is completely selected or if multiple lines are selected. * Being completely selected means that all characters except the new line characters are * selected. * * @return <code>true</code> if one or multiple lines are selected * @since 2.1 */ private boolean areMultipleLinesSelected(ITextViewer viewer) { if (viewer == null) return false; Point s= viewer.getSelectedRange(); if (s.y == 0) return false; try { IDocument document= viewer.getDocument(); int startLine= document.getLineOfOffset(s.x); int endLine= document.getLineOfOffset(s.x + s.y); IRegion line= document.getLineInformation(startLine); return startLine != endLine || (s.x == line.getOffset() && s.y == line.getLength()); } catch (BadLocationException x) { return false; } } } --- NEW FILE: TemplateContentAssistMessages.properties --- ############################################################################### # Copyright (c) 2000, 2005 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 ############################################################################### # template proposal # The first argument is the name and the second is the description TemplateProposal_displayString= {0} - {1} # template evaluator TemplateEvaluator_error_title=Template Evaluation Error --- NEW FILE: MultiVariableGuess.java --- /******************************************************************************* * Copyright (c) 2000, 2005 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.rubypeople.rdt.internal.ui.text.template.contentassist; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.jface.text.Assert; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.DocumentEvent; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.contentassist.ICompletionProposal; import org.eclipse.jface.text.contentassist.ICompletionProposalExtension2; import org.eclipse.jface.text.contentassist.IContextInformation; /** * Global state for templates. Selecting a proposal for the master template variable * will cause the value (and the proposals) for the slave variables to change. * * @see MultiVariable */ public class MultiVariableGuess { /** * Implementation of the <code>ICompletionProposal</code> interface and extension. */ class Proposal implements ICompletionProposal, ICompletionProposalExtension2 { /** The string to be displayed in the completion proposal popup */ private String fDisplayString; /** The replacement string */ String fReplacementString; /** The replacement offset */ private int fReplacementOffset; /** The replacement length */ private int fReplacementLength; /** The cursor position after this proposal has been applied */ private int fCursorPosition; /** The image to be displayed in the completion proposal popup */ private Image fImage; /** The context information of this proposal */ private IContextInformation fContextInformation; /** The additional info of this proposal */ private String fAdditionalProposalInfo; /** * Creates a new completion proposal based on the provided information. The replacement string is * considered being the display string too. All remaining fields are set to <code>null</code>. * * @param replacementString the actual string to be inserted into the document * @param replacementOffset the offset of the text to be replaced * @param replacementLength the length of the text to be replaced * @param cursorPosition the position of the cursor following the insert relative to replacementOffset */ public Proposal(String replacementString, int replacementOffset, int replacementLength, int cursorPosition) { this(replacementString, replacementOffset, replacementLength, cursorPosition, null, null, null, null); } /** * Creates a new completion proposal. All fields are initialized based on the provided information. * * @param replacementString the actual string to be inserted into the document * @param replacementOffset the offset of the text to be replaced * @param replacementLength the length of the text to be replaced * @param cursorPosition the position of the cursor following the insert relative to replacementOffset * @param image the image to display for this proposal * @param displayString the string to be displayed for the proposal * @param contextInformation the context information associated with this proposal * @param additionalProposalInfo the additional information associated with this proposal */ public Proposal(String replacementString, int replacementOffset, int replacementLength, int cursorPosition, Image image, String displayString, IContextInformation contextInformation, String additionalProposalInfo) { Assert.isNotNull(replacementString); Assert.isTrue(replacementOffset >= 0); Assert.isTrue(replacementLength >= 0); Assert.isTrue(cursorPosition >= 0); fReplacementString= replacementString; fReplacementOffset= replacementOffset; fReplacementLength= replacementLength; fCursorPosition= cursorPosition; fImage= image; fDisplayString= displayString; fContextInformation= contextInformation; fAdditionalProposalInfo= additionalProposalInfo; } /* * @see ICompletionProposal#apply(IDocument) */ public void apply(IDocument document) { try { document.replace(fReplacementOffset, fReplacementLength, fReplacementString); } catch (BadLocationException x) { // ignore } } /* * @see ICompletionProposal#getSelection(IDocument) */ public Point getSelection(IDocument document) { return new Point(fReplacementOffset + fCursorPosition, 0); } /* * @see ICompletionProposal#getContextInformation() */ public IContextInformation getContextInformation() { return fContextInformation; } /* * @see ICompletionProposal#getImage() */ public Image getImage() { return fImage; } /* * @see ICompletionProposal#getDisplayString() */ public String getDisplayString() { if (fDisplayString != null) return fDisplayString; return fReplacementString; } /* * @see ICompletionProposal#getAdditionalProposalInfo() */ public String getAdditionalProposalInfo() { return fAdditionalProposalInfo; } /* * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#apply(org.eclipse.jface.text.ITextViewer, char, int, int) */ public void apply(ITextViewer viewer, char trigger, int stateMask, int offset) { apply(viewer.getDocument()); } /* * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#selected(org.eclipse.jface.text.ITextViewer, boolean) */ public void selected(ITextViewer viewer, boolean smartToggle) { } /* * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#unselected(org.eclipse.jface.text.ITextViewer) */ public void unselected(ITextViewer viewer) { } /* * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#validate(org.eclipse.jface.text.IDocument, int, org.eclipse.jface.text.DocumentEvent) */ public boolean validate(IDocument document, int offset, DocumentEvent event) { try { String content= document.get(fReplacementOffset, fReplacementLength); if (content.startsWith(fReplacementString)) return true; } catch (BadLocationException e) { // ignore concurrently modified document } return false; } } private final List fSlaves= new ArrayList(); private MultiVariable fMaster; /** * @param mv */ public MultiVariableGuess(MultiVariable mv) { fMaster= mv; } /** * @param variable * @return */ public ICompletionProposal[] getProposals(MultiVariable variable, int offset, int length) { if (variable.equals(fMaster)) { String[] choices= variable.getValues(); ICompletionProposal[] ret= new ICompletionProposal[choices.length]; for (int i= 0; i < ret.length; i++) { ret[i]= new Proposal(choices[i], offset, length, offset + length) { /* * @see org.eclipse.jface.text.link.MultiVariableGuess.Proposal#apply(org.eclipse.jface.text.IDocument) */ public void apply(IDocument document) { super.apply(document); try { Object old= fMaster.getSet(); fMaster.setSet(fReplacementString); if (!fReplacementString.equals(old)) { for (Iterator it= fSlaves.iterator(); it.hasNext();) { VariablePosition pos= (VariablePosition) it.next(); String[] values= pos.getVariable().getValues(fReplacementString); if (values != null) document.replace(pos.getOffset(), pos.getLength(), values[0]); } } } catch (BadLocationException e) { // ignore and continue } } }; } return ret; } else { String[] choices= variable.getValues(fMaster.getSet()); if (choices == null || choices.length < 2) return null; ICompletionProposal[] ret= new ICompletionProposal[choices.length]; for (int i= 0; i < ret.length; i++) { ret[i]= new Proposal(choices[i], offset, length, offset + length); } return ret; } } /** * @param position */ public void addSlave(VariablePosition position) { fSlaves.add(position); } } --- NEW FILE: VariablePosition.java --- /******************************************************************************* * Copyright (c) 2000, 2005 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.rubypeople.rdt.internal.ui.text.template.contentassist; import org.eclipse.jface.text.Assert; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.contentassist.ICompletionProposal; import org.eclipse.jface.text.link.LinkedPositionGroup; import org.eclipse.jface.text.link.ProposalPosition; /** * */ public class VariablePosition extends ProposalPosition { private MultiVariableGuess fGuess; private MultiVariable fVariable; public VariablePosition(IDocument document, int offset, int length, MultiVariableGuess guess, MultiVariable variable) { this(document, offset, length, LinkedPositionGroup.NO_STOP, guess, variable); } public VariablePosition(IDocument document, int offset, int length, int sequence, MultiVariableGuess guess, MultiVariable variable) { super(document, offset, length, sequence, null); Assert.isNotNull(guess); Assert.isNotNull(variable); fVariable= variable; fGuess= guess; } /* * @see org.eclipse.jface.text.link.ProposalPosition#equals(java.lang.Object) */ public boolean equals(Object o) { if (o instanceof VariablePosition && super.equals(o)) { return fGuess.equals(((VariablePosition) o).fGuess); } return false; } /* * @see org.eclipse.jface.text.link.ProposalPosition#hashCode() */ public int hashCode() { return super.hashCode() | fGuess.hashCode(); } /* * @see org.eclipse.jface.text.link.ProposalPosition#getChoices() */ public ICompletionProposal[] getChoices() { return fGuess.getProposals(fVariable, offset, length); } /** * @return */ public MultiVariable getVariable() { return fVariable; } } --- NEW FILE: TemplateProposal.java --- /******************************************************************************* * Copyright (c) 2000, 2005 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.rubypeople.rdt.internal.ui.text.template.contentassist; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.BadPositionCategoryException; import org.eclipse.jface.text.DocumentEvent; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IInformationControlCreator; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.Position; import org.eclipse.jface.text.Region; import org.eclipse.jface.text.contentassist.ICompletionProposal; import org.eclipse.jface.text.contentassist.ICompletionProposalExtension2; import org.eclipse.jface.text.contentassist.ICompletionProposalExtension3; import org.eclipse.jface.text.contentassist.ICompletionProposalExtension4; import org.eclipse.jface.text.contentassist.IContextInformation; import org.eclipse.jface.text.link.ILinkedModeListener; import org.eclipse.jface.text.link.InclusivePositionUpdater; import org.eclipse.jface.text.link.LinkedModeModel; import org.eclipse.jface.text.link.LinkedModeUI; import org.eclipse.jface.text.link.LinkedPosition; import org.eclipse.jface.text.link.LinkedPositionGroup; import org.eclipse.jface.text.link.ProposalPosition; import org.eclipse.jface.text.templates.DocumentTemplateContext; import org.eclipse.jface.text.templates.GlobalTemplateVariables; import org.eclipse.jface.text.templates.Template; import org.eclipse.jface.text.templates.TemplateBuffer; import org.eclipse.jface.text.templates.TemplateContext; import org.eclipse.jface.text.templates.TemplateException; import org.eclipse.jface.text.templates.TemplateVariable; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.texteditor.link.EditorLinkedModeUI; import org.rubypeople.rdt.internal.corext.Assert; import org.rubypeople.rdt.internal.corext.template.ruby.RubyScriptContext; import org.rubypeople.rdt.internal.corext.util.Messages; import org.rubypeople.rdt.internal.ui.RubyPlugin; import org.rubypeople.rdt.internal.ui.rubyeditor.RubyEditor; import org.rubypeople.rdt.internal.ui.util.ExceptionHandler; import org.rubypeople.rdt.ui.text.ruby.IRubyCompletionProposal; /** * A template proposal. */ public class TemplateProposal implements IRubyCompletionProposal, ICompletionProposalExtension2, ICompletionProposalExtension3, ICompletionProposalExtension4 { private final Template fTemplate; private final TemplateContext fContext; private final Image fImage; private IRegion fRegion; private int fRelevance; private IRegion fSelectedRegion; // initialized by apply() private String fDisplayString; /** * Creates a template proposal with a template and its context. * * @param template * the template * @param context * the context in which the template was requested * @param region * the region this proposal applies to * @param image * the icon of the proposal */ public TemplateProposal(Template template, TemplateContext context, IRegion region, Image image) { Assert.isNotNull(template); Assert.isNotNull(context); Assert.isNotNull(region); fTemplate = template; fContext = context; fImage = image; fRegion = region; fDisplayString = null; fRelevance = computeRelevance(); } /** * Computes the relevance to match the relevance values generated by the * core content assistant. * * @return a sensible relevance value. */ private int computeRelevance() { // see org.eclipse.jdt.internal.codeassist.RelevanceConstants final int R_DEFAULT = 0; final int R_INTERESTING = 5; final int R_CASE = 10; final int R_NON_RESTRICTED = 3; final int R_EXACT_NAME = 4; final int R_INLINE_TAG = 31; int base = R_DEFAULT + R_INTERESTING + R_NON_RESTRICTED; try { if (fContext instanceof DocumentTemplateContext) { DocumentTemplateContext templateContext = (DocumentTemplateContext) fContext; IDocument document = templateContext.getDocument(); String content = document.get(fRegion.getOffset(), fRegion .getLength()); if (fTemplate.getName().startsWith(content)) base += R_CASE; if (fTemplate.getName().equalsIgnoreCase(content)) base += R_EXACT_NAME; } } catch (BadLocationException e) { // ignore - not a case sensitive match then } // see CompletionProposalCollector.computeRelevance // just under keywords, but better than packages final int TEMPLATE_RELEVANCE = 1; return base * 16 + TEMPLATE_RELEVANCE; } /* * @see ICompletionProposal#apply(IDocument) */ public final void apply(IDocument document) { // not called anymore } /* * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#apply(org.eclipse.jface.text.ITextViewer, * char, int, int) */ public void apply(ITextViewer viewer, char trigger, int stateMask, int offset) { try { fContext.setReadOnly(false); TemplateBuffer templateBuffer; try { templateBuffer = fContext.evaluate(fTemplate); } catch (TemplateException e1) { fSelectedRegion = fRegion; return; } int start = getReplaceOffset(); int end = getReplaceEndOffset(); end = Math.max(end, offset); // insert template string IDocument document = viewer.getDocument(); String templateString = templateBuffer.getString(); document.replace(start, end - start, templateString); // translate positions LinkedModeModel model = new LinkedModeModel(); TemplateVariable[] variables = templateBuffer.getVariables(); MultiVariableGuess guess = fContext instanceof RubyScriptContext ? ((RubyScriptContext) fContext) .getMultiVariableGuess() : null; boolean hasPositions = false; for (int i = 0; i != variables.length; i++) { TemplateVariable variable = variables[i]; if (variable.isUnambiguous()) continue; LinkedPositionGroup group = new LinkedPositionGroup(); int[] offsets = variable.getOffsets(); int length = variable.getLength(); LinkedPosition first; if (guess != null && variable instanceof MultiVariable) { first = new VariablePosition(document, offsets[0] + start, length, guess, (MultiVariable) variable); guess.addSlave((VariablePosition) first); } else { String[] values = variable.getValues(); ICompletionProposal[] proposals = new ICompletionProposal[values.length]; for (int j = 0; j < values.length; j++) { ensurePositionCategoryInstalled(document, model); Position pos = new Position(offsets[0] + start, length); document.addPosition(getCategory(), pos); proposals[j] = new PositionBasedCompletionProposal( values[j], pos, length); } if (proposals.length > 1) first = new ProposalPosition(document, offsets[0] + start, length, proposals); else first = new LinkedPosition(document, offsets[0] + start, length); } for (int j = 0; j != offsets.length; j++) if (j == 0) group.addPosition(first); else group.addPosition(new LinkedPosition(document, offsets[j] + start, length)); model.addGroup(group); hasPositions = true; } if (hasPositions) { model.forceInstall(); RubyEditor editor = getRubyEditor(); if (editor != null) { // FIXME Enable when we do marking occurences // model.addLinkingListener(new // EditorHighlightingSynchronizer(editor)); } LinkedModeUI ui = new EditorLinkedModeUI(model, viewer); ui.setExitPosition(viewer, getCaretOffset(templateBuffer) + start, 0, Integer.MAX_VALUE); ui.enter(); fSelectedRegion = ui.getSelectedRegion(); } else fSelectedRegion = new Region(getCaretOffset(templateBuffer) + start, 0); } catch (BadLocationException e) { RubyPlugin.log(e); openErrorDialog(viewer.getTextWidget().getShell(), e); fSelectedRegion = fRegion; } catch (BadPositionCategoryException e) { RubyPlugin.log(e); openErrorDialog(viewer.getTextWidget().getShell(), e); fSelectedRegion = fRegion; } } /** * Returns the currently active java editor, or <code>null</code> if it * cannot be determined. * * @return the currently active java editor, or <code>null</code> */ private RubyEditor getRubyEditor() { IEditorPart part = RubyPlugin.getActivePage().getActiveEditor(); if (part instanceof RubyEditor) return (RubyEditor) part; else return null; } /** * Returns the offset of the range in the document that will be replaced by * applying this template. * * @return the offset of the range in the document that will be replaced by * applying this template */ private int getReplaceOffset() { int start; if (fContext instanceof DocumentTemplateContext) { DocumentTemplateContext docContext = (DocumentTemplateContext) fContext; start = docContext.getStart(); } else { start = fRegion.getOffset(); } return start; } /** * Returns the end offset of the range in the document that will be replaced * by applying this template. * * @return the end offset of the range in the document that will be replaced * by applying this template */ private int getReplaceEndOffset() { int end; if (fContext instanceof DocumentTemplateContext) { DocumentTemplateContext docContext = (DocumentTemplateContext) fContext; end = docContext.getEnd(); } else { end = fRegion.getOffset() + fRegion.getLength(); } return end; } private void ensurePositionCategoryInstalled(final IDocument document, LinkedModeModel model) { if (!document.containsPositionCategory(getCategory())) { document.addPositionCategory(getCategory()); final InclusivePositionUpdater updater = new InclusivePositionUpdater( getCategory()); document.addPositionUpdater(updater); model.addLinkingListener(new ILinkedModeListener() { /* * @see org.eclipse.jface.text.link.ILinkedModeListener#left(org.eclipse.jface.text.link.LinkedModeModel, * int) */ public void left(LinkedModeModel environment, int flags) { try { document.removePositionCategory(getCategory()); } catch (BadPositionCategoryException e) { // ignore } document.removePositionUpdater(updater); } public void suspend(LinkedModeModel environment) { } public void resume(LinkedModeModel environment, int flags) { } }); } } private String getCategory() { return "TemplateProposalCategory_" + toString(); //$NON-NLS-1$ } private int getCaretOffset(TemplateBuffer buffer) { TemplateVariable[] variables = buffer.getVariables(); for (int i = 0; i != variables.length; i++) { TemplateVariable variable = variables[i]; if (variable.getType().equals(GlobalTemplateVariables.Cursor.NAME)) return variable.getOffsets()[0]; } return buffer.getString().length(); } /* * @see ICompletionProposal#getSelection(IDocument) */ public Point getSelection(IDocument document) { return new Point(fSelectedRegion.getOffset(), fSelectedRegion .getLength()); } /* * @see ICompletionProposal#getAdditionalProposalInfo() */ public String getAdditionalProposalInfo() { try { fContext.setReadOnly(true); TemplateBuffer templateBuffer; try { templateBuffer = fContext.evaluate(fTemplate); } catch (TemplateException e1) { return null; } return templateBuffer.getString(); } catch (BadLocationException e) { handleException(RubyPlugin.getActiveWorkbenchShell(), new CoreException(new Status(IStatus.ERROR, RubyPlugin .getPluginId(), IStatus.OK, "", e))); //$NON-NLS-1$ return null; } } /* * @see ICompletionProposal#getDisplayString() */ public String getDisplayString() { if (fDisplayString == null) { String[] arguments = new String[] { fTemplate.getName(), fTemplate.getDescription() }; fDisplayString = Messages .format( TemplateContentAssistMessages.TemplateProposal_displayString, arguments); } return fDisplayString; } public void setDisplayString(String displayString) { fDisplayString = displayString; } /* * @see ICompletionProposal#getImage() */ public Image getImage() { return fImage; } /* * @see ICompletionProposal#getContextInformation() */ public IContextInformation getContextInformation() { return null; } private void openErrorDialog(Shell shell, Exception e) { MessageDialog.openError(shell, TemplateContentAssistMessages.TemplateEvaluator_error_title, e .getMessage()); } private void handleException(Shell shell, CoreException e) { ExceptionHandler.handle(e, shell, TemplateContentAssistMessages.TemplateEvaluator_error_title, null); } /* * @see IRubyCompletionProposal#getRelevance() */ public int getRelevance() { return fRelevance; } public void setRelevance(int relevance) { fRelevance = relevance; } public Template getTemplate() { return fTemplate; } /* * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension3#getInformationControlCreator() */ public IInformationControlCreator getInformationControlCreator() { return new TemplateInformationControlCreator(); } /* * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#selected(org.eclipse.jface.text.ITextViewer, * boolean) */ public void selected(ITextViewer viewer, boolean smartToggle) { } /* * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#unselected(org.eclipse.jface.text.ITextViewer) */ public void unselected(ITextViewer viewer) { } /* * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#validate(org.eclipse.jface.text.IDocument, * int, org.eclipse.jface.text.DocumentEvent) */ public boolean validate(IDocument document, int offset, DocumentEvent event) { try { int replaceOffset = getReplaceOffset(); if (offset >= replaceOffset) { String content = document.get(replaceOffset, offset - replaceOffset); return fTemplate.getName().toLowerCase().startsWith( content.toLowerCase()); } } catch (BadLocationException e) { // concurrent modification - ignore } return false; } /* * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension3#getReplacementString() */ public CharSequence getPrefixCompletionText(IDocument document, int completionOffset) { // bug 114360 - don't make selection templates prefix-completable if (isSelectionTemplate()) return ""; //$NON-NLS-1$ return fTemplate.getName(); } /* * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension3#getReplacementOffset() */ public int getPrefixCompletionStart(IDocument document, int completionOffset) { return getReplaceOffset(); } /* * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension4#isAutoInsertable() */ public boolean isAutoInsertable() { if (isSelectionTemplate()) return false; return fTemplate.isAutoInsertable(); } /** * Returns <code>true</code> if the proposal has a selection, e.g. will * wrap some code. * * @return <code>true</code> if the proposals completion length is non * zero * @since 3.2 */ private boolean isSelectionTemplate() { if (fContext instanceof DocumentTemplateContext) { DocumentTemplateContext ctx = (DocumentTemplateContext) fContext; if (ctx.getCompletionLength() > 0) return true; } return false; } } --- NEW FILE: PositionBasedCompletionProposal.java --- /******************************************************************************* * Copyright (c) 2000, 2005 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.rubypeople.rdt.internal.ui.text.template.contentassist; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.jface.text.Assert; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.DocumentEvent; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.Position; import org.eclipse.jface.text.contentassist.ICompletionProposal; import org.eclipse.jface.text.contentassist.ICompletionProposalExtension; import org.eclipse.jface.text.contentassist.ICompletionProposalExtension2; import org.eclipse.jface.text.contentassist.IContextInformation; /** * An enhanced implementation of the <code>ICompletionProposal</code> interface implementing all the extension interfaces. * It uses a position to track its replacement offset and length. The position must be set up externally. */ public class PositionBasedCompletionProposal implements ICompletionProposal, ICompletionProposalExtension, ICompletionProposalExtension2 { /** The string to be displayed in the completion proposal popup */ private String fDisplayString; /** The replacement string */ private String fReplacementString; /** The replacement position. */ private Position fReplacementPosition; /** The cursor position after this proposal has been applied */ private int fCursorPosition; /** The image to be displayed in the completion proposal popup */ private Image fImage; /** The context information of this proposal */ private IContextInformation fContextInformation; /** The additional info of this proposal */ private String fAdditionalProposalInfo; /** * Creates a new completion proposal based on the provided information. The replacement string is * considered being the display string too. All remaining fields are set to <code>null</code>. * * @param replacementString the actual string to be inserted into the document * @param replacementPosition the position of the text to be replaced * @param cursorPosition the position of the cursor following the insert relative to replacementOffset */ public PositionBasedCompletionProposal(String replacementString, Position replacementPosition, int cursorPosition) { this(replacementString, replacementPosition, cursorPosition, null, null, null, null); } /** * Creates a new completion proposal. All fields are initialized based on the provided information. * * @param replacementString the actual string to be inserted into the document * @param replacementPosition the position of the text to be replaced * @param cursorPosition the position of the cursor following the insert relative to replacementOffset * @param image the image to display for this proposal * @param displayString the string to be displayed for the proposal * @param contextInformation the context information associated with this proposal * @param additionalProposalInfo the additional information associated with this proposal */ public PositionBasedCompletionProposal(String replacementString, Position replacementPosition, int cursorPosition, Image image, String displayString, IContextInformation contextInformation, String additionalProposalInfo) { Assert.isNotNull(replacementString); Assert.isTrue(replacementPosition != null); fReplacementString= replacementString; fReplacementPosition= replacementPosition; fCursorPosition= cursorPosition; fImage= image; fDisplayString= displayString; fContextInformation= contextInformation; fAdditionalProposalInfo= additionalProposalInfo; } /* * @see ICompletionProposal#apply(IDocument) */ public void apply(IDocument document) { try { document.replace(fReplacementPosition.getOffset(), fReplacementPosition.getLength(), fReplacementString); } catch (BadLocationException x) { // ignore } } /* * @see ICompletionProposal#getSelection(IDocument) */ public Point getSelection(IDocument document) { return new Point(fReplacementPosition.getOffset() + fCursorPosition, 0); } /* * @see ICompletionProposal#getContextInformation() */ public IContextInformation getContextInformation() { return fContextInformation; } /* * @see ICompletionProposal#getImage() */ public Image getImage() { return fImage; } /* * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getDisplayString() */ public String getDisplayString() { if (fDisplayString != null) return fDisplayString; return fReplacementString; } /* * @see ICompletionProposal#getAdditionalProposalInfo() */ public String getAdditionalProposalInfo() { return fAdditionalProposalInfo; } /* * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#apply(org.eclipse.jface.text.ITextViewer, char, int, int) */ public void apply(ITextViewer viewer, char trigger, int stateMask, int offset) { apply(viewer.getDocument()); } /* * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#selected(org.eclipse.jface.text.ITextViewer, boolean) */ public void selected(ITextViewer viewer, boolean smartToggle) { } /* * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#unselected(org.eclipse.jface.text.ITextViewer) */ public void unselected(ITextViewer viewer) { } /* * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#validate(org.eclipse.jface.text.IDocument, int, org.eclipse.jface.text.DocumentEvent) */ public boolean validate(IDocument document, int offset, DocumentEvent event) { try { String content= document.get(fReplacementPosition.getOffset(), offset - fReplacementPosition.getOffset()); if (fReplacementString.startsWith(content)) return true; } catch (BadLocationException e) { // ignore concurrently modified document } return false; } /* * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension#apply(org.eclipse.jface.text.IDocument, char, int) */ public void apply(IDocument document, char trigger, int offset) { // not called any more } /* * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension#isValidFor(org.eclipse.jface.text.IDocument, int) */ public boolean isValidFor(IDocument document, int offset) { // not called any more return false; } /* * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension#getTriggerCharacters() */ public char[] getTriggerCharacters() { return null; } /* * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension#getContextInformationPosition() */ public int getContextInformationPosition() { return fReplacementPosition.getOffset(); } } |