/******************************************************************************* * Copyright (c) 2009 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 * Zend Technologies *******************************************************************************/ package org.eclipse.php.internal.ui.editor.templates; import java.util.*; import org.eclipse.dltk.core.ISourceModule; import org.eclipse.dltk.ui.templates.IScriptTemplateIndenter; import org.eclipse.dltk.ui.templates.ScriptTemplateContext; import org.eclipse.dltk.ui.templates.ScriptTemplateContextType; import org.eclipse.dltk.utils.TextUtils; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.Position; import org.eclipse.jface.text.TextUtilities; import org.eclipse.jface.text.templates.*; import org.eclipse.php.internal.core.format.FormatterUtils; import org.eclipse.php.internal.core.format.IFormatterCommonPreferences; /** * The template's context */ public class PHPTemplateContext extends ScriptTemplateContext { private static final String DOLLAR = "dollar"; //$NON-NLS-1$ private static final String DOLLAR_SIGN = "$"; //$NON-NLS-1$ public static final char BLANK = ' '; public static final char TAB = '\t'; private String fLineDelimiter; public PHPTemplateContext(ScriptTemplateContextType phpTemplateContextType, IDocument document, int offset, int length, ISourceModule sourceModule) { super(phpTemplateContextType, document, offset, length, sourceModule); } public PHPTemplateContext(ScriptTemplateContextType phpTemplateContextType, IDocument document, Position position, ISourceModule sourceModule) { super(phpTemplateContextType, document, position, sourceModule); } @Override public TemplateBuffer evaluate(Template template) throws BadLocationException, TemplateException { IFormatterCommonPreferences prefs = FormatterUtils.getFormatterCommonPreferences(); boolean useTab = prefs.useTab(getDocument()); if (!useTab) { int length = prefs.getIndentationSize(getDocument()); StringBuilder sb = new StringBuilder(); for (int i = 0; i < length; i++) { sb.append(prefs.getIndentationChar(getDocument())); // $NON-NLS-1$ } String newPattern = TextUtils.replace(template.getPattern(), TAB, sb.toString()); template = new Template(template.getName(), template.getDescription(), template.getContextTypeId(), newPattern, template.isAutoInsertable()); } if (!canEvaluate(template)) return null; final String[] lines = TextUtils.splitLines(template.getPattern()); if (lines.length > 1) { String delimeter; if (fLineDelimiter == null) { delimeter = TextUtilities.getDefaultLineDelimiter(getDocument()); } else { delimeter = fLineDelimiter; } final String indent = calculateIndent(getDocument(), getStart()); final IScriptTemplateIndenter indenter = getIndenter(); final StringBuffer buffer = new StringBuffer(lines[0]); // Except first line for (int i = 1; i < lines.length; i++) { buffer.append(delimeter); indenter.indentLine(buffer, indent, lines[i]); } template = new Template(template.getName(), template.getDescription(), template.getContextTypeId(), buffer.toString(), template.isAutoInsertable()); } TemplateTranslator translator = new TemplateTranslator(); TemplateBuffer buffer = translator.translate(template); getContextType().resolve(buffer, this); TemplateBuffer result = buffer; // 300533: Switching through template keys? in fore and forek template // is corrupter // https://bugs.eclipse.org/bugs/show_bug.cgi?id=300533 // merge ${dollar}${variable} to single $variable to solve bug 300533 TemplateVariable[] variables = result.getVariables(); TemplateVariable dollarVariable = null; List<TemplateVariable> nonDollarVariables = new ArrayList<>(); for (int i = 0; i < variables.length; i++) { if (isDollar(variables[i])) { dollarVariable = variables[i]; } else { nonDollarVariables.add(variables[i]); } } List<TemplateVariable> templateVariables = new ArrayList<>(); if (dollarVariable != null) { Set<Integer> dollarOffsetSet = new HashSet<>(); for (int i = 0; i < dollarVariable.getOffsets().length; i++) { dollarOffsetSet.add(dollarVariable.getOffsets()[i]); } for (Iterator iterator = nonDollarVariables.iterator(); iterator.hasNext();) { TemplateVariable templateVariable = (TemplateVariable) iterator.next(); if (templateVariable.getOffsets().length > 0 && isbehind(templateVariable, dollarOffsetSet)) { int[] offsets = new int[templateVariable.getOffsets().length]; for (int i = 0; i < templateVariable.getOffsets().length; i++) { dollarOffsetSet.remove(templateVariable.getOffsets()[i] - 1); offsets[i] = templateVariable.getOffsets()[i] - 1; } String name = DOLLAR_SIGN + templateVariable.getName(); String defaultValue = name; if (templateVariable.getDefaultValue() != null) { defaultValue = DOLLAR_SIGN + templateVariable.getDefaultValue(); } templateVariable = new TemplateVariable(templateVariable.getVariableType(), name, defaultValue, offsets); } templateVariables.add(templateVariable); } if (!dollarOffsetSet.isEmpty()) { templateVariables.add(dollarVariable); } result.setContent(result.getString(), templateVariables.toArray(new TemplateVariable[templateVariables.size()])); } // end return result; } private boolean isbehind(TemplateVariable templateVariable, Set<Integer> dollarOffsetSet) { for (int i = 0; i < templateVariable.getOffsets().length; i++) { if (!dollarOffsetSet.contains(templateVariable.getOffsets()[i] - 1)) { return false; } } return true; } private boolean isDollar(TemplateVariable templateVariable) { return templateVariable.isUnambiguous() && DOLLAR.equals(templateVariable.getType()); } public void setLineDelimiter(String lineDelimiter) { this.fLineDelimiter = lineDelimiter; } }