| /******************************************************************************* |
| * Copyright (c) 2009 xored software, Inc. |
| * |
| * 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: |
| * xored software, Inc. - initial API and Implementation (Alex Panchenko) |
| *******************************************************************************/ |
| package org.eclipse.dltk.ui.util; |
| |
| import java.util.HashSet; |
| import java.util.Set; |
| |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.ProjectScope; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.Platform; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.core.runtime.preferences.IScopeContext; |
| import org.eclipse.core.runtime.preferences.InstanceScope; |
| import org.eclipse.dltk.compiler.util.Util; |
| import org.eclipse.dltk.core.IBuffer; |
| import org.eclipse.dltk.core.IModelElement; |
| import org.eclipse.dltk.core.IScriptProject; |
| import org.eclipse.dltk.core.ISourceModule; |
| import org.eclipse.dltk.core.ModelException; |
| import org.eclipse.dltk.internal.corext.util.Strings; |
| 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.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.SWT; |
| import org.eclipse.text.edits.DeleteEdit; |
| import org.eclipse.text.edits.InsertEdit; |
| import org.eclipse.text.edits.MalformedTreeException; |
| import org.eclipse.text.edits.MultiTextEdit; |
| |
| public class CodeGeneration { |
| |
| public static String evaluateTemplate(TemplateContext context, |
| Template template, String[] fullLineVariables) throws CoreException { |
| TemplateBuffer buffer; |
| try { |
| buffer = context.evaluate(template); |
| if (buffer == null) |
| return null; |
| String str = fixFullLineVariables(buffer, fullLineVariables); |
| if (Strings.containsOnlyWhitespaces(str)) { |
| return null; |
| } |
| return str; |
| } catch (BadLocationException e) { |
| throw new CoreException(Status.CANCEL_STATUS); |
| } catch (TemplateException e) { |
| throw new CoreException(Status.CANCEL_STATUS); |
| } |
| } |
| |
| // remove lines for empty variables, prefix multi-line variables |
| private static String fixFullLineVariables(TemplateBuffer buffer, |
| String[] variables) throws MalformedTreeException, |
| BadLocationException { |
| IDocument doc = new Document(buffer.getString()); |
| int nLines = doc.getNumberOfLines(); |
| MultiTextEdit edit = new MultiTextEdit(); |
| Set<Integer> removedLines = new HashSet<Integer>(); |
| for (int i = 0; i < variables.length; i++) { |
| TemplateVariable position = findVariable(buffer, variables[i]); |
| if (position == null) { |
| continue; |
| } |
| if (position.getLength() > 0) { |
| int[] offsets = position.getOffsets(); |
| for (int j = 0; j < offsets.length; j++) { |
| final int offset = offsets[j]; |
| try { |
| int startLine = doc.getLineOfOffset(offset); |
| int startOffset = doc.getLineOffset(startLine); |
| int endLine = doc.getLineOfOffset(offset |
| + position.getLength()); |
| String prefix = doc.get(startOffset, offset |
| - startOffset); |
| if (prefix.length() > 0 && startLine < endLine) { |
| for (int line = startLine + 1; line <= endLine; ++line) { |
| int lineOffset = doc.getLineOffset(line); |
| edit.addChild(new InsertEdit(lineOffset, prefix)); |
| } |
| } |
| } catch (BadLocationException exc) { |
| break; |
| } |
| } |
| } else { |
| int[] offsets = position.getOffsets(); |
| for (int k = 0; k < offsets.length; k++) { |
| int line = doc.getLineOfOffset(offsets[k]); |
| IRegion lineInfo = doc.getLineInformation(line); |
| int offset = lineInfo.getOffset(); |
| String str = doc.get(offset, lineInfo.getLength()); |
| if (Strings.containsOnlyWhitespaces(str) |
| && nLines > line + 1 && removedLines.add(line)) { |
| int nextStart = doc.getLineOffset(line + 1); |
| int length = nextStart - offset; |
| edit.addChild(new DeleteEdit(offset, length)); |
| } |
| } |
| } |
| } |
| edit.apply(doc, 0); |
| return doc.get(); |
| } |
| |
| private static TemplateVariable findVariable(TemplateBuffer buffer, |
| String variable) { |
| TemplateVariable[] positions = buffer.getVariables(); |
| for (int i = 0; i < positions.length; i++) { |
| TemplateVariable curr = positions[i]; |
| if (variable.equals(curr.getType())) { |
| return curr; |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Examines a string and returns the first line delimiter found. |
| */ |
| public static String getLineDelimiterUsed(IModelElement elem) |
| throws ModelException { |
| if (elem == null) |
| return Util.EMPTY_STRING; |
| |
| ISourceModule cu = (ISourceModule) elem |
| .getAncestor(IModelElement.SOURCE_MODULE); |
| if (cu != null && cu.exists()) { |
| IBuffer buf = cu.getBuffer(); |
| int length = buf.getLength(); |
| for (int i = 0; i < length; i++) { |
| char ch = buf.getChar(i); |
| if (ch == SWT.CR) { |
| if (i + 1 < length) { |
| if (buf.getChar(i + 1) == SWT.LF) { |
| return "\r\n"; //$NON-NLS-1$ |
| } |
| } |
| return "\r"; //$NON-NLS-1$ |
| } else if (ch == SWT.LF) { |
| return "\n"; //$NON-NLS-1$ |
| } |
| } |
| } |
| return getProjectLineDelimiter(elem.getScriptProject()); |
| } |
| |
| private static String getProjectLineDelimiter(IScriptProject cProject) { |
| IProject project = null; |
| if (cProject != null) |
| project = cProject.getProject(); |
| |
| String lineDelimiter = getLineDelimiterPreference(project); |
| if (lineDelimiter != null) |
| return lineDelimiter; |
| |
| return Util.LINE_SEPARATOR; |
| } |
| |
| public static String getLineDelimiterPreference(IProject project) { |
| IScopeContext[] scopeContext; |
| if (project != null) { |
| // project preference |
| scopeContext = new IScopeContext[] { new ProjectScope(project) }; |
| String lineDelimiter = Platform.getPreferencesService().getString( |
| Platform.PI_RUNTIME, Platform.PREF_LINE_SEPARATOR, null, |
| scopeContext); |
| if (lineDelimiter != null) |
| return lineDelimiter; |
| } |
| // workspace preference |
| scopeContext = new IScopeContext[] { InstanceScope.INSTANCE }; |
| String platformDefault = System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$ |
| return Platform.getPreferencesService().getString(Platform.PI_RUNTIME, |
| Platform.PREF_LINE_SEPARATOR, platformDefault, scopeContext); |
| } |
| |
| } |