Merge remote branch 'origin/master'

This commit is contained in:
Dmitry Jemerov
2011-12-09 16:31:46 +01:00
30 changed files with 409 additions and 134 deletions
@@ -41,6 +41,7 @@ import com.intellij.psi.util.PsiTypesUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.IncorrectOperationException;
import com.sun.jdi.Value;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
@@ -321,7 +322,10 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
if (rType == null) {
throwEvaluateException(DebuggerBundle.message("evaluation.error.unknown.expression.type", expression.getText()));
}
PsiType typeForBinOp = TypeConversionUtil.calcTypeForBinaryExpression(lType, rType, opType, true);
final PsiType typeForBinOp = TypeConversionUtil.calcTypeForBinaryExpression(lType, rType, opType, true);
if (typeForBinOp == null) {
throwEvaluateException(DebuggerBundle.message("evaluation.error.unknown.expression.type", wideExpression.getText()));
}
myResult = createBinaryEvaluator(result, lType, rResult, rType, opType, typeForBinOp);
lType = typeForBinOp;
result = myResult;
@@ -330,7 +334,7 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
// constructs binary evaluator handling unboxing and numeric promotion issues
private static BinaryExpressionEvaluator createBinaryEvaluator(
Evaluator lResult, final PsiType lType, Evaluator rResult, final PsiType rType, final IElementType operation, final PsiType expressionExpectedType) {
Evaluator lResult, final PsiType lType, Evaluator rResult, final PsiType rType, final IElementType operation, final @NotNull PsiType expressionExpectedType) {
// handle unboxing if neccesary
if (isUnboxingInBinaryExpressionApplicable(lType, rType, operation)) {
if (rType instanceof PsiClassType && UnBoxingEvaluator.isTypeUnboxable(rType.getCanonicalText())) {
@@ -394,7 +398,7 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
}
}
return new BinaryExpressionEvaluator(lResult, rResult, operation, expressionExpectedType == null ? null : expressionExpectedType.getCanonicalText());
return new BinaryExpressionEvaluator(lResult, rResult, operation, expressionExpectedType.getCanonicalText());
}
private static boolean isBinaryNumericPromotionApplicable(PsiType lType, PsiType rType, IElementType opType) {
@@ -134,6 +134,32 @@ public class GenerateConstructorHandler extends GenerateMembersHandlerBase {
return members;
}
@Override
protected MemberChooser<ClassMember> createMembersChooser(ClassMember[] members,
boolean allowEmptySelection,
boolean copyJavadocCheckbox,
Project project) {
final MemberChooser<ClassMember> chooser = super.createMembersChooser(members, allowEmptySelection, copyJavadocCheckbox, project);
final List<ClassMember> preselection = preselect(members);
if (!preselection.isEmpty()) {
chooser.selectElements(preselection.toArray(new ClassMember[preselection.size()]));
}
return chooser;
}
protected static List<ClassMember> preselect(ClassMember[] members) {
final List<ClassMember> preselection = new ArrayList<ClassMember>();
for (ClassMember member : members) {
if (member instanceof PsiFieldMember) {
final PsiField psiField = ((PsiFieldMember)member).getElement();
if (psiField != null && psiField.hasModifierProperty(PsiModifier.FINAL)) {
preselection.add(member);
}
}
}
return preselection;
}
@NotNull
protected List<? extends GenerationInfo> generateMemberPrototypes(PsiClass aClass, ClassMember[] members) throws IncorrectOperationException {
List<PsiMethod> baseConstructors = new ArrayList<PsiMethod>();
@@ -183,15 +183,23 @@ public abstract class GenerateMembersHandlerBase implements CodeInsightActionHan
@Nullable
protected ClassMember[] chooseMembers(ClassMember[] members, boolean allowEmptySelection, boolean copyJavadocCheckbox, Project project) {
MemberChooser<ClassMember> chooser = new MemberChooser<ClassMember>(members, allowEmptySelection, true, project);
chooser.setTitle(myChooserTitle);
chooser.setCopyJavadocVisible(copyJavadocCheckbox);
MemberChooser<ClassMember> chooser = createMembersChooser(members, allowEmptySelection, copyJavadocCheckbox, project);
chooser.show();
myToCopyJavaDoc = chooser.isCopyJavadoc();
final List<ClassMember> list = chooser.getSelectedElements();
return list == null ? null : list.toArray(new ClassMember[list.size()]);
}
protected MemberChooser<ClassMember> createMembersChooser(ClassMember[] members,
boolean allowEmptySelection,
boolean copyJavadocCheckbox,
Project project) {
MemberChooser<ClassMember> chooser = new MemberChooser<ClassMember>(members, allowEmptySelection, true, project);
chooser.setTitle(myChooserTitle);
chooser.setCopyJavadocVisible(copyJavadocCheckbox);
return chooser;
}
@NotNull
protected List<? extends GenerationInfo> generateMemberPrototypes(PsiClass aClass, ClassMember[] members) throws IncorrectOperationException {
ArrayList<GenerationInfo> array = new ArrayList<GenerationInfo>();
@@ -0,0 +1,11 @@
class Test {
private int a;
private final int b;
private int c;
private final int d;
Test(int b, int d) {
this.b = b;
this.d = d;
}
}
@@ -0,0 +1,6 @@
class Test {
private int a;
private final int b;
private int c;
private final int d;
}
@@ -10,6 +10,8 @@ import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.testFramework.LightCodeInsightTestCase;
import java.util.List;
public class GenerateConstructorTest extends LightCodeInsightTestCase {
public void testAbstractClass() throws Exception { doTest(); }
public void testPackageLocalClass() throws Exception { doTest(); }
@@ -38,6 +40,22 @@ public class GenerateConstructorTest extends LightCodeInsightTestCase {
doTest();
}
public void testFinalFieldPreselection() throws Exception {
String name = getTestName(false);
configureByFile("/codeInsight/generateConstructor/before" + name + ".java");
new GenerateConstructorHandler() {
@Override
protected ClassMember[] chooseMembers(ClassMember[] members,
boolean allowEmptySelection,
boolean copyJavadocCheckbox,
Project project) {
final List<ClassMember> preselection = GenerateConstructorHandler.preselect(members);
return preselection.toArray(new ClassMember[preselection.size()]);
}
}.invoke(getProject(), getEditor(), getFile());
checkResultByFile("/codeInsight/generateConstructor/after" + name +".java");
}
private void doTest() throws Exception {
String name = getTestName(false);
configureByFile("/codeInsight/generateConstructor/before" +
@@ -226,7 +226,7 @@ public class EditorSearchComponent extends JPanel implements DataProvider, Selec
myProject = project;
myEditor = editor;
mySearchResults = new SearchResults(myEditor);
mySearchResults = new SearchResults(myEditor, myProject);
myDefaultBackground = new JTextField().getBackground();
@@ -58,6 +58,7 @@ public class SearchResults implements DocumentListener {
private Set<RangeMarker> myExcluded = new HashSet<RangeMarker>();
private Editor myEditor;
private Project myProject;
private FindModel myFindModel;
private int myMatchesLimit = 100;
@@ -72,8 +73,9 @@ public class SearchResults implements DocumentListener {
private Stack<Pair<FindModel, LiveOccurrence>> myCursorPositions = new Stack<Pair<FindModel, LiveOccurrence>>();
public SearchResults(Editor editor) {
public SearchResults(Editor editor, Project project) {
myEditor = editor;
myProject = project;
myEditor.getDocument().addDocumentListener(this);
}
@@ -161,7 +163,7 @@ public class SearchResults implements DocumentListener {
@Nullable
public Project getProject() {
return myEditor.getProject();
return myProject;
}
public synchronized void setEditor(Editor editor) {
@@ -328,7 +330,7 @@ public class SearchResults implements DocumentListener {
int offset = r.getStartOffset();
while (true) {
FindManager findManager = FindManager.getInstance(editor.getProject());
FindManager findManager = FindManager.getInstance(getProject());
FindResult result;
try {
BombedCharSequence
@@ -29,7 +29,7 @@ import com.intellij.openapi.vfs.VirtualFile;
/**
* @author yole
*/
public class FilePromptMacro extends Macro implements SecondQueueExpandMacro {
public class FilePromptMacro extends PromptingMacro implements SecondQueueExpandMacro {
@Override
public String getName() {
return "FilePrompt";
@@ -40,16 +40,12 @@ public class FilePromptMacro extends Macro implements SecondQueueExpandMacro {
return "Shows a file chooser dialog";
}
@Override
public String expand(DataContext dataContext) throws ExecutionCancelledException {
protected String promptUser(DataContext dataContext) {
Project project = PlatformDataKeys.PROJECT.getData(dataContext);
final FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleLocalFileDescriptor();
final FileChooserDialog fileChooser = FileChooserFactory.getInstance().createFileChooser(descriptor, project);
final VirtualFile[] result = fileChooser.choose(null, project);
if (result.length != 1) {
throw new ExecutionCancelledException();
}
return FileUtil.toSystemDependentName(result [0].getPath());
return result.length == 1? FileUtil.toSystemDependentName(result[0].getPath()) : null;
}
@Override
@@ -158,14 +158,17 @@ public final class MacroManager {
}
public String expandSilentMarcos(String str, boolean firstQueueExpand, DataContext dataContext) throws Macro.ExecutionCancelledException {
return expandMacroSet(str, firstQueueExpand, dataContext,
ConvertingIterator.create(getMacros().iterator(), new Convertor<Macro, Macro>() {
public Macro convert(Macro macro) {
if (macro instanceof PromptMacro)
return new Macro.Silent(macro, "");
return macro;
}
}));
final Convertor<Macro, Macro> convertor = new Convertor<Macro, Macro>() {
public Macro convert(Macro macro) {
if (macro instanceof PromptingMacro) {
return new Macro.Silent(macro, "");
}
return macro;
}
};
return expandMacroSet(
str, firstQueueExpand, dataContext, ConvertingIterator.create(getMacros().iterator(), convertor)
);
}
}
@@ -19,8 +19,9 @@ package com.intellij.ide.macro;
import com.intellij.ide.IdeBundle;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.ui.Messages;
import org.jetbrains.annotations.Nullable;
public final class PromptMacro extends Macro implements SecondQueueExpandMacro {
public final class PromptMacro extends PromptingMacro implements SecondQueueExpandMacro {
public String getName() {
return "Prompt";
}
@@ -29,11 +30,9 @@ public final class PromptMacro extends Macro implements SecondQueueExpandMacro {
return IdeBundle.message("macro.prompt");
}
public String expand(DataContext dataContext) throws ExecutionCancelledException {
String userInput = Messages.showInputDialog(IdeBundle.message("prompt.enter.parameters"),
IdeBundle.message("title.input"), Messages.getQuestionIcon());
if (userInput == null) throw new ExecutionCancelledException();
return userInput;
@Nullable
protected String promptUser(DataContext dataContext) {
return Messages.showInputDialog(IdeBundle.message("prompt.enter.parameters"), IdeBundle.message("title.input"), Messages.getQuestionIcon());
}
public void cachePreview(DataContext dataContext) {
@@ -0,0 +1,44 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.ide.macro;
import com.intellij.openapi.actionSystem.DataContext;
import org.jetbrains.annotations.Nullable;
/**
* @author Eugene Zhuravlev
* Date: 12/9/11
*/
public abstract class PromptingMacro extends Macro{
public final String expand(DataContext dataContext) throws ExecutionCancelledException {
final String userInput = promptUser(dataContext);
if (userInput == null) {
throw new ExecutionCancelledException();
}
return userInput;
}
/**
* Called from expand() method
*
* @param dataContext
* @return user input. If null is returned, ExecutionCancelledException is thrown by expand() method
*/
@Nullable
protected abstract String promptUser(DataContext dataContext);
}
@@ -290,10 +290,10 @@ dialog.edit.template.label.abbreviation=&Abbreviation:
dialog.edit.template.label.group=&Group:
dialog.edit.template.label.description=&Description:
dialog.edit.template.options.title=Options
dialog.edit.template.label.expand.with=&Expand with
dialog.edit.template.label.expand.with=E&xpand with
dialog.edit.template.checkbox.reformat.according.to.style=&Reformat according to style
dialog.edit.template.checkbox.shorten.fq.names=Shorten &FQ names
dialog.edit.template.checkbox.use.static.import=Use static import if possible
dialog.edit.template.checkbox.use.static.import=Use static &import if possible
dialog.edit.template.context.title=Context
dialog.edit.template.checkbox.html=&HTML
dialog.edit.template.checkbox.xml=&XML
@@ -101,8 +101,7 @@ error.message.connection.already.open=Connection already open
checkbox.text.use.internal.ssh.implementation=Use &internal ssh implementation
dialog.title.select.path.to.external.rsh=Select Path to External Rsh
dialog.title.select.path.to.ssh.private.key=Select Path to Ssh Private Key
dialog.title.select.path.to.cvs.client=Select Path to CVS Client
dialog.description.select.path.to.cvs.client=Select path to CVS client
dialog.title.select.path.to.cvs.client=Select path to CVS executable
error.title.invalid.cvs.root=Invalid CVS Root
error.message.timeout.error=Timeout error.
error.dialog.title.timeout.error=Timeout Error
@@ -347,6 +346,7 @@ command.name.rollback.file.creation=Rollback file creation
border.title.update.options.other.settings=Other Settings
border.title.update.options.updating.group=Updating
border.title.ext.protocol.settings=Ext Protocol Settings
border.title.local.protocol.settings=Local Protocol Settings
border.title.configure.ssh.private.key.file=Private Key File
border.title.configure.ssh.ssh.version=SSH version
border.title.configure.proxy.proxy.settings=Proxy Settings
@@ -91,7 +91,7 @@ public class Cvs2SettingsEditPanel {
myConnectionSettingsPanel.setLayout(new CardLayout());
myExtConnectionSettingsEditor = new ExtConnectionDualPanel();
mySshConnectionSettingsEditor = new SshConnectionSettingsPanel();
myLocalConnectionSettingsPanel = new LocalConnectionSettingsPanel();
myLocalConnectionSettingsPanel = new LocalConnectionSettingsPanel(project);
myConnectionSettingsPanel.add(myExtConnectionSettingsEditor.getPanel(), CvsMethod.EXT_METHOD.getDisplayName());
myConnectionSettingsPanel.add(new JPanel(), CvsMethod.PSERVER_METHOD.getDisplayName());
myConnectionSettingsPanel.add(mySshConnectionSettingsEditor.getPanel(), CvsMethod.SSH_METHOD.getDisplayName());
@@ -121,7 +121,9 @@ public class Cvs2SettingsEditPanel {
myProxySettingsPanel.add(myProxySettingsNonEmptyPanel.getPanel(), NON_EMPTY_PROXY_SETTINGS);
myProxySettingsPanel.add(new JPanel(), EMPTY);
if (readOnly) setEnabled(myDateOrRevisionOrTagSettingsPanel, false);
if (readOnly) {
setEnabled(myDateOrRevisionOrTagSettingsPanel, false);
}
}
public void addCvsRootChangeListener(CvsRootChangeListener cvsRootChangeListener) {
@@ -6,7 +6,10 @@
<xy x="16" y="26" width="591" height="112"/>
</constraints>
<properties/>
<border type="none"/>
<clientProperties>
<BorderFactoryClass class="java.lang.String" value="com.intellij.ui.IdeBorderFactory$PlainSmallWithIndent"/>
</clientProperties>
<border type="etched" title-resource-bundle="com/intellij/cvsSupport2/CvsBundle" title-key="border.title.local.protocol.settings"/>
<children>
<grid id="3c730" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@ package com.intellij.cvsSupport2.connections.local.ui;
import com.intellij.CvsBundle;
import com.intellij.cvsSupport2.config.LocalSettings;
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import javax.swing.*;
@@ -30,9 +31,8 @@ public class LocalConnectionSettingsPanel {
private TextFieldWithBrowseButton myPathToCvsClient;
private JPanel myPanel;
public LocalConnectionSettingsPanel() {
myPathToCvsClient.addBrowseFolderListener(CvsBundle.message("dialog.title.select.path.to.cvs.client"),
CvsBundle.message("dialog.description.select.path.to.cvs.client"), null,
public LocalConnectionSettingsPanel(Project project) {
myPathToCvsClient.addBrowseFolderListener(CvsBundle.message("dialog.title.select.path.to.cvs.client"), null, project,
FileChooserDescriptorFactory.createSingleFileNoJarsDescriptor());
}
@@ -15,6 +15,7 @@
*/
package org.intellij.lang.xpath.psi.impl;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
@@ -35,6 +36,8 @@ import java.util.Collections;
import java.util.List;
public class ResolveUtil {
public static final Key<List<PsiElement>> DEPENDENCIES = Key.create("XSLT_DEPENDENCIES");
@SuppressWarnings({"unchecked"})
private final THashSet<PsiElement> myHistory = new THashSet<PsiElement>(TObjectHashingStrategy.IDENTITY);
@@ -145,8 +145,7 @@ public class XPathFunctionCallImpl extends XPathElementImpl implements XPathFunc
if (name == null) return null;
final Function functionDecl = contextProvider.getFunctionContext().resolve(name, getArgumentList().length);
final XPathFunction impl = functionDecl instanceof XPathFunction ? (XPathFunction)functionDecl : new FunctionImpl(functionDecl);
final XPathFunction impl = functionDecl == null ? null : functionDecl instanceof XPathFunction ? (XPathFunction)functionDecl : new FunctionImpl(functionDecl);
return (myFunction = Pair.create(getQName().toString(), impl)).second;
}
}
@@ -15,11 +15,19 @@
*/
package org.intellij.lang.xpath.xslt.context;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.UserDataCache;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.CachedValuesManager;
import com.intellij.psi.util.ParameterizedCachedValue;
import com.intellij.psi.util.ParameterizedCachedValueProvider;
import com.intellij.psi.xml.XmlElement;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.ArrayUtil;
import com.intellij.util.SmartList;
import org.apache.commons.collections.map.CompositeMap;
import org.intellij.lang.xpath.context.ContextType;
import org.intellij.lang.xpath.context.XPathVersion;
@@ -27,21 +35,25 @@ import org.intellij.lang.xpath.context.functions.Function;
import org.intellij.lang.xpath.context.functions.FunctionContext;
import org.intellij.lang.xpath.psi.XPath2Type;
import org.intellij.lang.xpath.psi.XPathType;
import org.intellij.lang.xpath.psi.impl.ResolveUtil;
import org.intellij.lang.xpath.xslt.XsltSupport;
import org.intellij.lang.xpath.xslt.psi.XsltElementFactory;
import org.intellij.lang.xpath.xslt.psi.XsltFunction;
import org.intellij.lang.xpath.xslt.util.QNameUtil;
import org.intellij.lang.xpath.xslt.psi.XsltStylesheet;
import org.intellij.lang.xpath.xslt.util.XsltCodeInsightUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.xml.namespace.QName;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Xslt2ContextProvider extends XsltContextProviderBase {
public static final ContextType TYPE = ContextType.lookupOrCreate("XSLT2", XPathVersion.V2);
private static final Key<ParameterizedCachedValue<Map<Pair<QName,Integer>,Function>,XmlFile>> FUNCTIONS = Key.create("XSLT_FUNCTIONS");
protected Xslt2ContextProvider(@NotNull XmlElement contextElement) {
super(contextElement);
}
@@ -115,45 +127,57 @@ public class Xslt2ContextProvider extends XsltContextProviderBase {
Xslt2FunctionContext.getInstance();
}
private static Map<Pair<QName, Integer>, Function> getCustomFunctions(XmlFile file) {
final XmlTag rootTag = file.getRootTag();
assert rootTag != null;
final XmlTag[] functionTags = rootTag.findSubTags("function", XsltSupport.XSLT_NS);
final Map<Pair<QName, Integer>, Function> candidates = new HashMap<Pair<QName, Integer>, Function>();
for (XmlTag tag : functionTags) {
final String n = tag.getAttributeValue("name");
if (n == null) continue;
final XsltFunction f = XsltElementFactory.getInstance().wrapElement(tag, XsltFunction.class);
candidates.put(Pair.create(f.getQName(), f.getParameters().length), f);
private static final UserDataCache<ParameterizedCachedValue<Map<Pair<QName,Integer>,Function>,XmlFile>, XmlFile, Void> ourFunctionCacheProvider =
new UserDataCache<ParameterizedCachedValue<Map<Pair<QName,Integer>,Function>,XmlFile>, XmlFile, Void>() {
@Override
protected ParameterizedCachedValue<Map<Pair<QName,Integer>,Function>,XmlFile> compute(XmlFile file, Void p) {
return CachedValuesManager.getManager(file.getProject()).createParameterizedCachedValue(MyFunctionProvider.INSTANCE, false);
}
return candidates;
};
private static Map<Pair<QName, Integer>, Function> getCustomFunctions(XmlFile file) {
return ourFunctionCacheProvider.get(FUNCTIONS, file, null).getValue(file);
}
@Nullable
private static Function resolveCustomFunction(final XmlFile file, final QName name, int argCount) {
final XmlTag rootTag = file.getRootTag();
assert rootTag != null;
final XmlTag[] functionTags = rootTag.findSubTags("function", XsltSupport.XSLT_NS);
XsltFunction candidate = null;
for (XmlTag tag : functionTags) {
final String n = tag.getAttributeValue("name");
if (n == null) continue;
final QName fName = QNameUtil.createQName(n, tag);
if (fName.equals(name)) {
candidate = XsltElementFactory.getInstance().wrapElement(tag, XsltFunction.class);
if (candidate.getParameters().length == argCount) { // TODO: overrride=[yes|no]
return candidate;
}
}
final Map<Pair<QName, Integer>, Function> functions = getCustomFunctions(file);
final Function exactMatch = functions.get(Pair.create(name, argCount));
if (exactMatch != null) {
return exactMatch;
}
Function candidate = null;
for (Pair<QName, Integer> pair : functions.keySet()) {
if (pair.getFirst().equals(name)) {
candidate = functions.get(pair);
}
}
return candidate;
}
private static class MyFunctionProvider implements ParameterizedCachedValueProvider<Map<Pair<QName, Integer>, Function>, XmlFile> {
private static ParameterizedCachedValueProvider<Map<Pair<QName,Integer>,Function>,XmlFile> INSTANCE = new MyFunctionProvider();
@Override
public CachedValueProvider.Result<Map<Pair<QName, Integer>, Function>> compute(XmlFile param) {
final XmlTag rootTag = param.getRootTag();
assert rootTag != null;
final Map<Pair<QName, Integer>, Function> candidates = new HashMap<Pair<QName, Integer>, Function>();
final XsltFunction[] functions = XsltElementFactory.getInstance().wrapElement(rootTag, XsltStylesheet.class).getFunctions();
for (XsltFunction function : functions) {
candidates.put(Pair.create(function.getQName(), function.getParameters().length), function);
}
List<PsiElement> data = param.getUserData(ResolveUtil.DEPENDENCIES);
if (data == null) {
data = new SmartList<PsiElement>(param);
} else {
data.add(param);
param.putUserData(ResolveUtil.DEPENDENCIES, null);
}
return CachedValueProvider.Result.create(candidates, ArrayUtil.toObjectArray(data));
}
}
}
@@ -18,7 +18,8 @@ package org.intellij.lang.xpath.xslt.psi;
import org.jetbrains.annotations.NotNull;
public interface XsltStylesheet extends XsltElement {
@NotNull
@NotNull
XsltParameter[] getParameters();
/**
@@ -29,4 +30,7 @@ public interface XsltStylesheet extends XsltElement {
@NotNull
XsltTemplate[] getTemplates();
@NotNull
XsltFunction[] getFunctions();
}
@@ -15,47 +15,70 @@
*/
package org.intellij.lang.xpath.xslt.psi.impl;
import org.intellij.lang.xpath.psi.impl.ResolveUtil;
import org.intellij.lang.xpath.xslt.psi.XsltParameter;
import org.intellij.lang.xpath.xslt.psi.XsltStylesheet;
import org.intellij.lang.xpath.xslt.psi.XsltTemplate;
import org.intellij.lang.xpath.xslt.psi.XsltVariable;
import org.intellij.lang.xpath.xslt.util.ParamMatcher;
import org.intellij.lang.xpath.xslt.util.TemplateMatcher;
import org.intellij.lang.xpath.xslt.XsltSupport;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.xml.XmlDocument;
import com.intellij.psi.xml.XmlTag;
import org.intellij.lang.xpath.psi.impl.ResolveUtil;
import org.intellij.lang.xpath.xslt.XsltSupport;
import org.intellij.lang.xpath.xslt.psi.*;
import org.intellij.lang.xpath.xslt.util.IncludeAwareMatcher;
import org.intellij.lang.xpath.xslt.util.ParamMatcher;
import org.intellij.lang.xpath.xslt.util.TemplateMatcher;
import org.jetbrains.annotations.NotNull;
public class XsltStylesheetImpl extends XsltElementImpl implements XsltStylesheet {
public XsltStylesheetImpl(XmlTag target) {
super(target);
public XsltStylesheetImpl(XmlTag target) {
super(target);
}
@NotNull
public XsltParameter[] getParameters() {
return convertArray(ResolveUtil.collect(new ParamMatcher(getTag(), null)), XsltParameter.class);
}
@NotNull
public XsltVariable[] getVariables() {
return convertArray(ResolveUtil.collect(new ParamMatcher(getTag(), null) {
protected boolean isApplicable(XmlTag tag) {
return XsltSupport.isVariable(tag);
}
}), XsltVariable.class);
}
@NotNull
public XsltTemplate[] getTemplates() {
final XmlDocument document = PsiTreeUtil.getParentOfType(getTag(), XmlDocument.class);
return convertArray(ResolveUtil.collect(new TemplateMatcher(document)), XsltTemplate.class);
}
@NotNull
@Override
public XsltFunction[] getFunctions() {
final XmlDocument document = PsiTreeUtil.getParentOfType(getTag(), XmlDocument.class);
return convertArray(ResolveUtil.collect(new FunctionMatcher(document)), XsltFunction.class);
}
@Override
public String toString() {
return "XsltStylesheet";
}
private class FunctionMatcher extends IncludeAwareMatcher {
public FunctionMatcher(XmlDocument document) {
super(document);
}
@NotNull
public XsltParameter[] getParameters() {
return convertArray(ResolveUtil.collect(new ParamMatcher(getTag(), null)), XsltParameter.class);
protected boolean matches(XmlTag element) {
return XsltSupport.isFunction(element);
}
@NotNull
public XsltVariable[] getVariables() {
return convertArray(ResolveUtil.collect(new ParamMatcher(getTag(), null) {
protected boolean isApplicable(XmlTag tag) {
return XsltSupport.isVariable(tag);
}
}), XsltVariable.class);
protected ResolveUtil.Matcher changeDocument(XmlDocument document) {
return new FunctionMatcher(document);
}
@NotNull
public XsltTemplate[] getTemplates() {
final XmlDocument document = PsiTreeUtil.getParentOfType(getTag(), XmlDocument.class);
return convertArray(ResolveUtil.collect(new TemplateMatcher(document)), XsltTemplate.class);
}
@Override
public String toString() {
return "XsltStylesheet";
public ResolveUtil.Matcher variantMatcher() {
return new FunctionMatcher(myDocument);
}
}
}
@@ -15,6 +15,8 @@
*/
package org.intellij.lang.xpath.xslt.util;
import com.intellij.psi.PsiElement;
import com.intellij.util.SmartList;
import org.intellij.lang.xpath.psi.impl.ResolveUtil;
import org.intellij.lang.xpath.xslt.XsltSupport;
@@ -25,6 +27,8 @@ import com.intellij.psi.xml.XmlDocument;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public abstract class IncludeAwareMatcher extends BaseMatcher {
protected final XmlDocument myDocument;
@@ -49,7 +53,15 @@ public abstract class IncludeAwareMatcher extends BaseMatcher {
final PsiFile file = ResolveUtil.resolveFile(href, f);
if (file instanceof XmlFile) {
return Result.create(changeDocument(((XmlFile)file).getDocument()));
final List<PsiElement> data = myDocument.getContainingFile().getUserData(ResolveUtil.DEPENDENCIES);
if (data == null) {
myDocument.getContainingFile().putUserData(ResolveUtil.DEPENDENCIES, new SmartList<PsiElement>(file));
} else if (!data.contains(file)) {
data.add(file);
}
return Result.create(changeDocument(((XmlFile)file).getDocument()));
}
}
} else {
@@ -15,19 +15,17 @@
*/
package org.intellij.lang.xpath.xslt;
import org.intellij.lang.xpath.TestBase;
import org.intellij.lang.xpath.psi.XPathVariableReference;
import org.intellij.lang.xpath.xslt.psi.XsltElement;
import org.intellij.lang.xpath.xslt.psi.XsltParameter;
import org.intellij.lang.xpath.xslt.psi.XsltTemplate;
import org.intellij.lang.xpath.xslt.psi.XsltVariable;
import org.intellij.lang.xpath.xslt.util.XsltCodeInsightUtil;
import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiPolyVariantReference;
import com.intellij.psi.PsiReference;
import com.intellij.psi.ResolveResult;
import com.intellij.util.ArrayUtil;
import org.intellij.lang.xpath.TestBase;
import org.intellij.lang.xpath.psi.XPathFunctionCall;
import org.intellij.lang.xpath.psi.XPathVariableReference;
import org.intellij.lang.xpath.xslt.psi.*;
import org.intellij.lang.xpath.xslt.util.XsltCodeInsightUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -50,6 +48,14 @@ public class XsltResolveTest extends TestBase {
doVariableResolveTest(false);
}
public void testResolveIncludedFunction() throws Throwable {
doFunctionResolveTest("included-2.xsl");
}
public void testResolveFunction() throws Throwable {
doFunctionResolveTest();
}
public void testResolveSameName() throws Throwable {
final XsltVariable variable = doVariableResolveTest(false);
@@ -99,9 +105,22 @@ public class XsltResolveTest extends TestBase {
return var;
}
private XsltFunction doFunctionResolveTest(String... files) throws Throwable {
final PsiReference reference = findInjectedReferenceAtCaret(files);
final PsiElement element = reference.resolve();
assertTrue(element instanceof XsltFunction);
final XsltFunction func = (XsltFunction)element;
final XPathFunctionCall call = (XPathFunctionCall)reference.getElement();
assertEquals(func.getName(), call.getFunctionName());
assertEquals(func.getParameters().length, call.getArgumentList().length);
return func;
}
@NotNull
private PsiReference findInjectedReferenceAtCaret() throws Throwable {
configure();
private PsiReference findInjectedReferenceAtCaret(String... moreFiles) throws Throwable {
configure(moreFiles);
final InjectedLanguageManager manager = InjectedLanguageManager.getInstance(myFixture.getProject());
final PsiElement e = manager.findInjectedElementAt(myFixture.getFile(), myFixture.getEditor().getCaretModel().getOffset());
@@ -112,8 +131,8 @@ public class XsltResolveTest extends TestBase {
return reference;
}
private void configure() throws Throwable {
myFixture.configureByFile(getTestFileName() + ".xsl");
private void configure(String... moreFiles) throws Throwable {
myFixture.configureByFiles(ArrayUtil.mergeArrays(new String[]{getTestFileName() + ".xsl"}, moreFiles));
}
@Override
@@ -0,0 +1,5 @@
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:nsx="nsx">
<xsl:function name="nsx:func1" as="xs:boolean+">
<xsl:sequence select="(false(), true())"/>
</xsl:function>
</xsl:stylesheet>
@@ -0,0 +1,9 @@
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:nsx="nsx" xmlns:xs="http://www.w3.org/2001/XMLSchema" >
<xsl:function name="nsx:func1" as="xs:boolean+">
<xsl:sequence select="(false(), true())"/>
</xsl:function>
<xsl:template match="/">
<xsl:variable name="test" select="nsx:func1<caret>()" />
</xsl:template>
</xsl:stylesheet>
@@ -0,0 +1,7 @@
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:nsx="nsx">
<xsl:import href="included-2.xsl" />
<xsl:template match="/">
<xsl:variable name="test" select="nsx:func1<caret>()" />
</xsl:template>
</xsl:stylesheet>
@@ -21,17 +21,20 @@ import net.sf.saxon.expr.instruct.GeneralVariable;
import net.sf.saxon.expr.instruct.GlobalVariable;
import net.sf.saxon.expr.instruct.LocalVariable;
import net.sf.saxon.expr.instruct.SlotManager;
import net.sf.saxon.functions.FunctionLibrary;
import net.sf.saxon.om.*;
import net.sf.saxon.style.*;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.type.ItemType;
import net.sf.saxon.type.Type;
import net.sf.saxon.type.TypeHierarchy;
import net.sf.saxon.value.SequenceType;
import org.intellij.plugins.xsltDebugger.rt.engine.Debugger;
import org.intellij.plugins.xsltDebugger.rt.engine.Value;
import org.intellij.plugins.xsltDebugger.rt.engine.local.VariableImpl;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -186,12 +189,10 @@ class Saxon9StyleFrame<N extends StyleElement> extends AbstractSaxon9Frame<Debug
myItemType = itemType;
}
@Override
public Object getValue() {
return myValue != null ? myValue.getStringValue() : null;
}
@Override
public Type getType() {
return new ObjectType(myItemType.toString());
}
@@ -211,12 +212,10 @@ class Saxon9StyleFrame<N extends StyleElement> extends AbstractSaxon9Frame<Debug
myItemType = type;
}
@Override
public Object getValue() {
return myValue;
}
@Override
public Type getType() {
return new ObjectType(myItemType.toString() + "+");
}
@@ -242,6 +241,11 @@ class Saxon9StyleFrame<N extends StyleElement> extends AbstractSaxon9Frame<Debug
myElement = element;
}
@Override
public FunctionLibrary getFunctionLibrary() {
return new FunctionLibraryWrapper(myElement);
}
@Override
public Expression bindVariable(StructuredQName qName) throws XPathException {
final VariableReference expression = (VariableReference)super.bindVariable(qName);
@@ -277,8 +281,60 @@ class Saxon9StyleFrame<N extends StyleElement> extends AbstractSaxon9Frame<Debug
o = myRedundant.get(variable);
myRedundant.set(variable, value);
} catch (IllegalAccessException e) {
debug(e);
}
return (Boolean)o;
}
private static class FunctionLibraryWrapper implements FunctionLibrary {
private static Method myGetFunction;
static {
try {
myGetFunction = PrincipalStylesheetModule.class.getDeclaredMethod("getFunction", StructuredQName.class, int.class);
myGetFunction.setAccessible(true);
} catch (Exception e) {
e.printStackTrace();
myGetFunction = null;
}
}
private final FunctionLibrary myLibrary;
private final PrincipalStylesheetModule myModule;
public FunctionLibraryWrapper(StyleElement element) {
myLibrary = element.getStaticContext().getFunctionLibrary();
myModule = element.getPrincipalStylesheetModule();
}
public SequenceType[] getFunctionSignature(StructuredQName functionName, int arity) {
return myLibrary.getFunctionSignature(functionName, arity);
}
public Expression bind(StructuredQName functionName, Expression[] staticArgs, StaticContext env, Container container)
throws XPathException {
final Expression call = myLibrary.bind(functionName, staticArgs, env, container);
if (call instanceof UserFunctionCall) {
final XSLFunction fn = getFunction(functionName, staticArgs);
if (fn != null) {
((UserFunctionCall)call).setFunction(fn.getCompiledFunction());
}
}
return call;
}
private XSLFunction getFunction(StructuredQName functionName, Expression[] staticArgs) {
if (myGetFunction == null) return null;
try {
return (XSLFunction)myGetFunction.invoke(myModule, functionName, staticArgs.length);
} catch (Exception e) {
debug(e);
return null;
}
}
public FunctionLibrary copy() {
return this;
}
}
}
}
@@ -111,17 +111,14 @@ public class Saxon9TraceListener implements TraceListener {
super(previous, new MySource(instr));
}
@Override
public String getInstruction() {
return getPrevious().getInstruction();
}
@Override
public Value eval(String expr) throws Debugger.EvaluationException {
return getPrevious().eval(expr);
}
@Override
public List<Debugger.Variable> getVariables() {
return getPrevious().getVariables();
}
@@ -133,26 +130,21 @@ public class Saxon9TraceListener implements TraceListener {
myInstruction = instr;
}
@Override
public void setSystemId(String systemId) {
}
@Override
public String getPublicId() {
return null;
}
@Override
public String getSystemId() {
return myInstruction.getSystemId();
}
@Override
public int getLineNumber() {
return myInstruction.getLineNumber();
}
@Override
public int getColumnNumber() {
return myInstruction.getColumnNumber();
}
@@ -33,7 +33,7 @@ public class XsltStackFrame extends XStackFrame {
@Override
public Object getEqualityObject() {
return super.getEqualityObject();
return XsltStackFrame.class;
}
@Override