diff --git a/ExtendedApi/ExtendedApi.iml b/ExtendedApi/ExtendedApi.iml new file mode 100644 index 000000000000..6e121a399bbd --- /dev/null +++ b/ExtendedApi/ExtendedApi.iml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/source/com/intellij/psi/impl/source/ASTWrapperPsiElement.java b/ExtendedApi/src/com/intellij/psi/impl/source/ASTWrapperPsiElement.java similarity index 91% rename from source/com/intellij/psi/impl/source/ASTWrapperPsiElement.java rename to ExtendedApi/src/com/intellij/psi/impl/source/ASTWrapperPsiElement.java index 55c37e02b13d..d498536b1405 100644 --- a/source/com/intellij/psi/impl/source/ASTWrapperPsiElement.java +++ b/ExtendedApi/src/com/intellij/psi/impl/source/ASTWrapperPsiElement.java @@ -14,11 +14,16 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; import com.intellij.psi.impl.ElementBase; import com.intellij.psi.impl.SharedPsiElementImplUtil; +import com.intellij.psi.impl.source.resolve.ResolveUtil; +import com.intellij.psi.impl.source.tree.CompositeElement; import com.intellij.psi.scope.PsiScopeProcessor; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.SearchScope; import com.intellij.util.IncorrectOperationException; +import java.util.ArrayList; +import java.util.List; + /** * Created by IntelliJ IDEA. * User: max @@ -43,7 +48,15 @@ public class ASTWrapperPsiElement extends ElementBase implements PsiElement, Nav } public PsiElement[] getChildren() { - return new PsiElement[0]; + List result = new ArrayList(); + ASTNode child = getNode().getFirstChildNode(); + while (child != null) { + if (child instanceof CompositeElement) { + result.add(childNodeToPsi(child)); + } + child = child.getTreeNext(); + } + return result.toArray(new PsiElement[result.size()]); } public PsiElement getParent() { @@ -209,7 +222,7 @@ public class ASTWrapperPsiElement extends ElementBase implements PsiElement, Nav } public PsiElement getContext() { - throw new UnsupportedOperationException(); + return ResolveUtil.getContext(this); } public boolean isPhysical() { @@ -262,6 +275,10 @@ public class ASTWrapperPsiElement extends ElementBase implements PsiElement, Nav return myNode; } + public PsiElement childNodeToPsi(ASTNode node) { + return SourceTreeToPsiMap.treeElementToPsi(node); + } + public Language getLanguage() { return myNode.getElementType().getLanguage(); } diff --git a/source/com/intellij/testFramework/EditorActionTestCase.java b/ExtendedApi/src/com/intellij/testFramework/EditorActionTestCase.java similarity index 100% rename from source/com/intellij/testFramework/EditorActionTestCase.java rename to ExtendedApi/src/com/intellij/testFramework/EditorActionTestCase.java diff --git a/source/com/intellij/testFramework/IdeaTestCase.java b/ExtendedApi/src/com/intellij/testFramework/IdeaTestCase.java similarity index 100% rename from source/com/intellij/testFramework/IdeaTestCase.java rename to ExtendedApi/src/com/intellij/testFramework/IdeaTestCase.java diff --git a/source/com/intellij/testFramework/LightCodeInsightTestCase.java b/ExtendedApi/src/com/intellij/testFramework/LightCodeInsightTestCase.java similarity index 100% rename from source/com/intellij/testFramework/LightCodeInsightTestCase.java rename to ExtendedApi/src/com/intellij/testFramework/LightCodeInsightTestCase.java diff --git a/source/com/intellij/testFramework/LightIdeaTestCase.java b/ExtendedApi/src/com/intellij/testFramework/LightIdeaTestCase.java similarity index 98% rename from source/com/intellij/testFramework/LightIdeaTestCase.java rename to ExtendedApi/src/com/intellij/testFramework/LightIdeaTestCase.java index ae6b8f7c3049..519ddef77e87 100644 --- a/source/com/intellij/testFramework/LightIdeaTestCase.java +++ b/ExtendedApi/src/com/intellij/testFramework/LightIdeaTestCase.java @@ -26,7 +26,6 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.ex.dummy.DummyFileSystem; import com.intellij.openapi.vfs.impl.VirtualFilePointerManagerImpl; import com.intellij.openapi.vfs.pointers.VirtualFilePointerManager; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; import com.intellij.psi.codeStyle.CodeStyleSettings; @@ -57,10 +56,7 @@ public class LightIdeaTestCase extends TestCase implements DataProvider { private static VirtualFile ourSourceRoot; private static TestCase ourTestCase = null; public static Thread ourTestThread; - - static { - Logger.setFactory(TestLoggerFactory.getInstance()); - } + private String oldCodeStyleSettings; /** * @return Project to be used in tests for example for project components retrieval. diff --git a/source/com/intellij/testFramework/LoggedErrorProcessor.java b/ExtendedApi/src/com/intellij/testFramework/LoggedErrorProcessor.java similarity index 100% rename from source/com/intellij/testFramework/LoggedErrorProcessor.java rename to ExtendedApi/src/com/intellij/testFramework/LoggedErrorProcessor.java diff --git a/source/com/intellij/testFramework/MockVirtualFile.java b/ExtendedApi/src/com/intellij/testFramework/MockVirtualFile.java similarity index 100% rename from source/com/intellij/testFramework/MockVirtualFile.java rename to ExtendedApi/src/com/intellij/testFramework/MockVirtualFile.java diff --git a/source/com/intellij/testFramework/ModuleTestCase.java b/ExtendedApi/src/com/intellij/testFramework/ModuleTestCase.java similarity index 100% rename from source/com/intellij/testFramework/ModuleTestCase.java rename to ExtendedApi/src/com/intellij/testFramework/ModuleTestCase.java diff --git a/testSource/com/intellij/psi/ParsingTestCase.java b/ExtendedApi/src/com/intellij/testFramework/ParsingTestCase.java similarity index 81% rename from testSource/com/intellij/psi/ParsingTestCase.java rename to ExtendedApi/src/com/intellij/testFramework/ParsingTestCase.java index f35f060c44cc..da66fc6d7c0b 100644 --- a/testSource/com/intellij/psi/ParsingTestCase.java +++ b/ExtendedApi/src/com/intellij/testFramework/ParsingTestCase.java @@ -1,11 +1,11 @@ -package com.intellij.psi; +package com.intellij.testFramework; import com.intellij.openapi.application.ex.PathManagerEx; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.PsiFile; import com.intellij.psi.impl.DebugUtil; -import com.intellij.testFramework.LightIdeaTestCase; import java.io.File; import java.io.FileNotFoundException; @@ -18,10 +18,14 @@ public abstract class ParsingTestCase extends LightIdeaTestCase { public ParsingTestCase(String dataPath, String fileExt) { myDataPath = dataPath; - myFullDataPath = PathManagerEx.getTestDataPath() + "/psi/" + myDataPath; + myFullDataPath = testDataPath() + "/psi/" + myDataPath; myFileExt = fileExt; } + protected String testDataPath() { + return PathManagerEx.getTestDataPath(); + } + protected void doTest(boolean checkResult) throws Exception{ String name = getTestName(false); String text = loadFile(name + "." + myFileExt); @@ -30,12 +34,12 @@ public abstract class ParsingTestCase extends LightIdeaTestCase { checkResult(name + ".txt", file); } else{ - DebugUtil.treeToString(com.intellij.psi.impl.source.SourceTreeToPsiMap.psiElementToTree(file), false); + toParseTreeText(file); } } protected void checkResult(String targetDataName, final PsiFile file) throws Exception { - String treeText = DebugUtil.treeToString(com.intellij.psi.impl.source.SourceTreeToPsiMap.psiElementToTree(file), false).trim(); + String treeText = toParseTreeText(file).trim(); try{ String expectedText = loadFile(targetDataName); /* @@ -63,6 +67,10 @@ public abstract class ParsingTestCase extends LightIdeaTestCase { } } + private String toParseTreeText(final PsiFile file) { + return DebugUtil.treeToString(com.intellij.psi.impl.source.SourceTreeToPsiMap.psiElementToTree(file), false); + } + protected String loadFile(String name) throws Exception { String fullName = myFullDataPath + File.separatorChar + name; String text = new String(FileUtil.loadFileText(new File(fullName))).trim(); diff --git a/source/com/intellij/testFramework/PsiTestCase.java b/ExtendedApi/src/com/intellij/testFramework/PsiTestCase.java similarity index 100% rename from source/com/intellij/testFramework/PsiTestCase.java rename to ExtendedApi/src/com/intellij/testFramework/PsiTestCase.java diff --git a/source/com/intellij/testFramework/PsiTestData.java b/ExtendedApi/src/com/intellij/testFramework/PsiTestData.java similarity index 100% rename from source/com/intellij/testFramework/PsiTestData.java rename to ExtendedApi/src/com/intellij/testFramework/PsiTestData.java diff --git a/source/com/intellij/testFramework/PsiTestUtil.java b/ExtendedApi/src/com/intellij/testFramework/PsiTestUtil.java similarity index 100% rename from source/com/intellij/testFramework/PsiTestUtil.java rename to ExtendedApi/src/com/intellij/testFramework/PsiTestUtil.java diff --git a/source/com/intellij/testFramework/TestEditorManagerImpl.java b/ExtendedApi/src/com/intellij/testFramework/TestEditorManagerImpl.java similarity index 100% rename from source/com/intellij/testFramework/TestEditorManagerImpl.java rename to ExtendedApi/src/com/intellij/testFramework/TestEditorManagerImpl.java diff --git a/source/com/intellij/testFramework/TestLogger.java b/ExtendedApi/src/com/intellij/testFramework/TestLogger.java similarity index 100% rename from source/com/intellij/testFramework/TestLogger.java rename to ExtendedApi/src/com/intellij/testFramework/TestLogger.java diff --git a/source/com/intellij/testFramework/TestLoggerFactory.java b/ExtendedApi/src/com/intellij/testFramework/TestLoggerFactory.java similarity index 100% rename from source/com/intellij/testFramework/TestLoggerFactory.java rename to ExtendedApi/src/com/intellij/testFramework/TestLoggerFactory.java diff --git a/source/com/intellij/testFramework/TestSourceBasedTestCase.java b/ExtendedApi/src/com/intellij/testFramework/TestSourceBasedTestCase.java similarity index 100% rename from source/com/intellij/testFramework/TestSourceBasedTestCase.java rename to ExtendedApi/src/com/intellij/testFramework/TestSourceBasedTestCase.java index 6ab7648c00a3..d5212ad91ce8 100644 --- a/source/com/intellij/testFramework/TestSourceBasedTestCase.java +++ b/ExtendedApi/src/com/intellij/testFramework/TestSourceBasedTestCase.java @@ -31,14 +31,14 @@ */ package com.intellij.testFramework; -import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.application.ex.PathManagerEx; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ex.PathManagerEx; +import com.intellij.openapi.roots.ContentEntry; import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.roots.ModuleRootManager; -import com.intellij.openapi.roots.ContentEntry; -import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.LocalFileSystem; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiManager; diff --git a/openapi/src/com/intellij/lang/ASTNode.java b/openapi/src/com/intellij/lang/ASTNode.java index 105131285cf8..752f908dce5c 100644 --- a/openapi/src/com/intellij/lang/ASTNode.java +++ b/openapi/src/com/intellij/lang/ASTNode.java @@ -1,10 +1,10 @@ package com.intellij.lang; -import com.intellij.psi.tree.IElementType; -import com.intellij.psi.tree.TokenSet; +import com.intellij.openapi.util.Key; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.UserDataHolder; -import com.intellij.openapi.util.Key; +import com.intellij.psi.tree.IElementType; +import com.intellij.psi.tree.TokenSet; /** * Created by IntelliJ IDEA. @@ -14,6 +14,8 @@ import com.intellij.openapi.util.Key; * To change this template use File | Settings | File Templates. */ public interface ASTNode extends UserDataHolder { + ASTNode[] EMPTY_ARRAY = new ASTNode[0]; + IElementType getElementType(); String getText(); @@ -59,4 +61,8 @@ public interface ASTNode extends UserDataHolder { T getCopyableUserData(Key key); void putCopyableUserData(Key key, T value); + + ASTNode findChildByType(IElementType type); + + ASTNode[] findChildrenByFilter(TokenSet filter); } diff --git a/openapi/src/com/intellij/lang/Language.java b/openapi/src/com/intellij/lang/Language.java index c9c9d0a67adf..70f1cbc79f33 100644 --- a/openapi/src/com/intellij/lang/Language.java +++ b/openapi/src/com/intellij/lang/Language.java @@ -43,7 +43,7 @@ public abstract class Language { return null; } - public ParserDefinition getParserDefinition(Project project) { + public ParserDefinition getParserDefinition() { return null; } diff --git a/openapi/src/com/intellij/lang/PsiBuilder.java b/openapi/src/com/intellij/lang/PsiBuilder.java index 3c6b1e042505..c25a0ae2ce07 100644 --- a/openapi/src/com/intellij/lang/PsiBuilder.java +++ b/openapi/src/com/intellij/lang/PsiBuilder.java @@ -1,7 +1,6 @@ package com.intellij.lang; import com.intellij.psi.tree.IElementType; -import com.intellij.psi.PsiElement; /** * Created by IntelliJ IDEA. @@ -11,28 +10,20 @@ import com.intellij.psi.PsiElement; * To change this template use File | Settings | File Templates. */ public interface PsiBuilder { + IElementType getTokenType(); + interface Marker { - } - - interface Lexem { - IElementType getTokenType(); - - String getTokenText(); + Marker preceed(); + void drop(); + void rollbackTo(); + void done(IElementType type); } void advanceLexer(); - Lexem getCurrentLexem(); + Marker mark(); - Marker start(IElementType symbol); - - void rollbackTo(Marker marker); - - void drop(Marker marker); - - void done(Marker marker); - - void insertErrorElement(String messageText); + void error(String messageText); boolean eof(); diff --git a/openapi/src/com/intellij/psi/tree/TokenSet.java b/openapi/src/com/intellij/psi/tree/TokenSet.java index f5a4a2be82bc..de5b989f4f23 100644 --- a/openapi/src/com/intellij/psi/tree/TokenSet.java +++ b/openapi/src/com/intellij/psi/tree/TokenSet.java @@ -36,6 +36,7 @@ import gnu.trove.THashSet; import java.util.Arrays; public class TokenSet { + public static final TokenSet EMPTY = new TokenSet(); private final THashSet mySet = new THashSet(100, (float)0.1); public IElementType[] getTypes() { diff --git a/source/com/intellij/lang/dtd/DTDLanguage.java b/source/com/intellij/lang/dtd/DTDLanguage.java index 2d08e064e786..fc81663d0c7b 100644 --- a/source/com/intellij/lang/dtd/DTDLanguage.java +++ b/source/com/intellij/lang/dtd/DTDLanguage.java @@ -23,7 +23,7 @@ public class DTDLanguage extends Language { return new XmlFileHighlighter(true); } - public ParserDefinition getParserDefinition(Project project) { + public ParserDefinition getParserDefinition() { return new DTDParserDefinition(); } } diff --git a/source/com/intellij/lang/html/HTMLLanguage.java b/source/com/intellij/lang/html/HTMLLanguage.java index bb072a3e133e..c91f5efdddf6 100644 --- a/source/com/intellij/lang/html/HTMLLanguage.java +++ b/source/com/intellij/lang/html/HTMLLanguage.java @@ -33,7 +33,7 @@ public class HTMLLanguage extends XMLLanguage { return ENCODE_EACH_SYMBOL_POLICY; } - public ParserDefinition getParserDefinition(Project project) { + public ParserDefinition getParserDefinition() { return new HTMLParserDefinition(); } } diff --git a/source/com/intellij/lang/impl/PsiBuilderImpl.java b/source/com/intellij/lang/impl/PsiBuilderImpl.java index 6677fd35d2c4..1b6a065cff0b 100644 --- a/source/com/intellij/lang/impl/PsiBuilderImpl.java +++ b/source/com/intellij/lang/impl/PsiBuilderImpl.java @@ -6,6 +6,7 @@ import com.intellij.lexer.Lexer; import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.impl.source.tree.*; import com.intellij.psi.tree.IElementType; +import com.intellij.psi.tree.TokenSet; import com.intellij.util.CharTable; import java.util.ArrayList; @@ -21,39 +22,65 @@ import java.util.List; public class PsiBuilderImpl implements PsiBuilder { private static final Logger LOG = Logger.getInstance("#com.intellij.lang.impl.PsiBuilderImpl"); - private List myLexems = new ArrayList(); - private List myProduction = new ArrayList(); + private List myLexems = new ArrayList(); + private List myProduction = new ArrayList(); private Lexer myLexer; private boolean myFileLevelParsing; + private TokenSet myWhitespaces; + private TokenSet myComments; private int myCurrentLexem; private CharTable myCharTable; - private boolean myStarted = false; - public PsiBuilderImpl(final Lexer lexer, final CharTable charTable, boolean fileLevelParsing) { + public PsiBuilderImpl(final Lexer lexer, final CharTable charTable, boolean fileLevelParsing, TokenSet whitespaces, TokenSet comments) { myCharTable = charTable; myLexer = lexer; myFileLevelParsing = fileLevelParsing; + myWhitespaces = whitespaces; + myComments = comments; } - private static class MarkerImpl implements Marker { + private class StartMarker extends ProductionMarker implements Marker { public IElementType myType; - public int myLexemIndex; public DoneMarker myDoneMarker = null; - public MarkerImpl(final IElementType type, int idx) { + public StartMarker(int idx) { + super(idx); + } + + public Marker preceed() { + return PsiBuilderImpl.this.preceed(this); + } + + public void drop() { + PsiBuilderImpl.this.drop(this); + } + + public void rollbackTo() { + PsiBuilderImpl.this.rollbackTo(this); + } + + public void done(IElementType type) { myType = type; - myLexemIndex = idx; + PsiBuilderImpl.this.done(this); } } - private class LexemImpl implements Lexem { + private Marker preceed(final StartMarker marker) { + int idx = myProduction.indexOf(marker); + LOG.assertTrue(idx >= 0, "Cannot preceed dropped or rolled-back marker"); + StartMarker pre = new StartMarker(marker.myLexemIndex); + myProduction.add(idx, pre); + return pre; + } + + public class Token { private IElementType myTokenType; private int myTokenStart; private int myTokenEnd; private int myState; - public LexemImpl() { + public Token() { myTokenType = myLexer.getTokenType(); myTokenStart = myLexer.getTokenStart(); myTokenEnd = myLexer.getTokenEnd(); @@ -69,50 +96,74 @@ public class PsiBuilderImpl implements PsiBuilder { } } - private static class DoneMarker { - public MarkerImpl myMarker; + private static class ProductionMarker { + public int myLexemIndex; - public DoneMarker(final MarkerImpl marker) { - myMarker = marker; + public ProductionMarker(final int lexemIndex) { + myLexemIndex = lexemIndex; } } - private static class ErrorItem { + private static class DoneMarker extends ProductionMarker { + public StartMarker myStart; + + public DoneMarker(final StartMarker marker, int currentLexem) { + super(currentLexem); + myStart = marker; + } + } + + private static class ErrorItem extends ProductionMarker { String myMessage; - public ErrorItem(final String message) { + public ErrorItem(final String message, int idx) { + super(idx); myMessage = message; } } + public IElementType getTokenType() { + final Token lex = getCurrentToken(); + final IElementType tokenType = lex == null ? null : lex.getTokenType(); + LOG.assertTrue(!whitespaceOrComment(tokenType)); + return tokenType; + } + public void advanceLexer() { - myProduction.add(getCurrentLexem()); myCurrentLexem++; - if (myCurrentLexem > myLexems.size()) { - LOG.assertTrue(!eof()); - final Lexem lxm = advanceOriginalLexer(); - if (lxm == null) return; - myLexems.add(lxm); + } + + public Token getCurrentToken() { + Token lastToken; + while(true) { + lastToken = getTokenOrWhitespace(); + if (lastToken == null) return null; + if (whitespaceOrComment(lastToken.getTokenType())) { + myCurrentLexem++; + } + else { + break; + } } + + return lastToken; } - private Lexem advanceOriginalLexer() { - myLexer.advance(); - return myLexer.getTokenType() == null ? null : new LexemImpl(); - } - - - public Lexem getCurrentLexem() { + private Token getTokenOrWhitespace() { + if (myCurrentLexem >= myLexems.size()) { + if (myLexer.getTokenType() == null) return null; + myLexems.add(new Token()); + myLexer.advance(); + } return myLexems.get(myCurrentLexem); } - public Marker start(IElementType symbol) { - if (!myStarted) { - myStarted = true; - myLexems.add(new LexemImpl()); - } + private boolean whitespaceOrComment(IElementType token) { + return myWhitespaces.isInSet(token) || myComments.isInSet(token); + } - MarkerImpl marker = new MarkerImpl(symbol, myCurrentLexem); + public Marker mark() { + StartMarker marker = new StartMarker(myCurrentLexem); myProduction.add(marker); return marker; } @@ -120,14 +171,11 @@ public class PsiBuilderImpl implements PsiBuilder { public boolean eof() { if (myCurrentLexem + 1 < myLexems.size()) return false; if (myLexer.getTokenType() == null) return true; - final Lexem lxm = advanceOriginalLexer(); - if (lxm == null) return true; - myLexems.add(lxm); - return false; + return getCurrentToken() == null; } public void rollbackTo(Marker marker) { - myCurrentLexem = ((MarkerImpl)marker).myLexemIndex; + myCurrentLexem = ((StartMarker)marker).myLexemIndex; int idx = myProduction.lastIndexOf(marker); LOG.assertTrue(idx >= 0, "The marker must be added before rolled back to."); @@ -142,31 +190,31 @@ public class PsiBuilderImpl implements PsiBuilder { } public void done(Marker marker) { - LOG.assertTrue(((MarkerImpl)marker).myDoneMarker == null, "Marker already done."); + LOG.assertTrue(((StartMarker)marker).myDoneMarker == null, "Marker already done."); int idx = myProduction.lastIndexOf(marker); LOG.assertTrue(idx >= 0, "Marker never been added."); for (int i = myProduction.size() - 1; i > idx; i--) { Object item = myProduction.get(i); if (item instanceof Marker) { - MarkerImpl otherMarker = (MarkerImpl)item; + StartMarker otherMarker = (StartMarker)item; if (otherMarker.myDoneMarker == null) { LOG.error("Another not done marker of type [" + otherMarker.myType + "] added after this one. Must be done before this."); } } } - DoneMarker doneMarker = new DoneMarker((MarkerImpl)marker); - ((MarkerImpl)marker).myDoneMarker = doneMarker; + DoneMarker doneMarker = new DoneMarker((StartMarker)marker, myCurrentLexem); + ((StartMarker)marker).myDoneMarker = doneMarker; myProduction.add(doneMarker); } - public void insertErrorElement(String messageText) { - myProduction.add(new ErrorItem(messageText)); + public void error(String messageText) { + myProduction.add(new ErrorItem(messageText, myCurrentLexem)); } public ASTNode getTreeBuilt() { - MarkerImpl rootMarker = (MarkerImpl)myProduction.get(0); + StartMarker rootMarker = (StartMarker)myProduction.get(0); final ASTNode rootNode; if (myFileLevelParsing) { @@ -179,28 +227,22 @@ public class PsiBuilderImpl implements PsiBuilder { } ASTNode curNode = rootNode; + int curToken = 0; for (int i = 1; i < myProduction.size(); i++) { LOG.assertTrue(curNode != null, "Unexpected end of the production"); - Object item = myProduction.get(i); - if (item instanceof LexemImpl) { - LexemImpl lexem = (LexemImpl)item; - final LeafPsiElement childNode = new LeafPsiElement(lexem.getTokenType(), - myLexer.getBuffer(), - lexem.myTokenStart, - lexem.myTokenEnd, - lexem.myState, - myCharTable); - TreeUtil.addChildren((CompositeElement)curNode, childNode); - } - else if (item instanceof MarkerImpl) { - MarkerImpl marker = (MarkerImpl)item; + ProductionMarker item = myProduction.get(i); + int lexIndex = item.myLexemIndex; + if (item instanceof StartMarker) { + StartMarker marker = (StartMarker)item; + curToken = insertLeafs(curToken, lexIndex, curNode); ASTNode childNode = new CompositeElement(marker.myType); TreeUtil.addChildren((CompositeElement)curNode, (TreeElement)childNode); curNode = childNode; } else if (item instanceof DoneMarker) { DoneMarker doneMarker = (DoneMarker)item; - LOG.assertTrue(doneMarker.myMarker.myType == curNode.getElementType()); + curToken = insertLeafs(curToken, lexIndex, curNode); + LOG.assertTrue(doneMarker.myStart.myType == curNode.getElementType()); curNode = curNode.getTreeParent(); } else if (item instanceof ErrorItem) { @@ -210,8 +252,24 @@ public class PsiBuilderImpl implements PsiBuilder { } } + LOG.assertTrue(curToken == myLexems.size(), "Not all of the tokens inserted to the tree"); LOG.assertTrue(curNode == null, "Unbalanced tree"); return rootNode; } + + private int insertLeafs(int curToken, final int lastIdx, final ASTNode curNode) { + while (curToken < lastIdx) { + Token lexem = myLexems.get(curToken++); + final IElementType type = lexem.getTokenType(); + final LeafPsiElement childNode = new LeafPsiElement(type, + myLexer.getBuffer(), + lexem.myTokenStart, + lexem.myTokenEnd, + lexem.myState, + myCharTable); + TreeUtil.addChildren((CompositeElement)curNode, childNode); + } + return curToken; + } } diff --git a/source/com/intellij/lang/java/JavaLanguage.java b/source/com/intellij/lang/java/JavaLanguage.java index b678c5ced904..bb8b03fc8ccc 100644 --- a/source/com/intellij/lang/java/JavaLanguage.java +++ b/source/com/intellij/lang/java/JavaLanguage.java @@ -37,7 +37,7 @@ public class JavaLanguage extends Language { }; } - public ParserDefinition getParserDefinition(Project project) { + public ParserDefinition getParserDefinition() { return new JavaParserDefinition(); } } diff --git a/source/com/intellij/lang/xhtml/XHTMLLanguage.java b/source/com/intellij/lang/xhtml/XHTMLLanguage.java index 22573c413c09..89873fb13430 100644 --- a/source/com/intellij/lang/xhtml/XHTMLLanguage.java +++ b/source/com/intellij/lang/xhtml/XHTMLLanguage.java @@ -32,7 +32,7 @@ public class XHTMLLanguage extends XMLLanguage { return ENCODE_EACH_SYMBOL_POLICY; } - public ParserDefinition getParserDefinition(Project project) { + public ParserDefinition getParserDefinition() { return new XHTMLParserDefinition(); } } diff --git a/source/com/intellij/lang/xml/XMLLanguage.java b/source/com/intellij/lang/xml/XMLLanguage.java index 35df4956cda1..bf9caede1380 100644 --- a/source/com/intellij/lang/xml/XMLLanguage.java +++ b/source/com/intellij/lang/xml/XMLLanguage.java @@ -43,7 +43,7 @@ public class XMLLanguage extends Language { return CDATA_ON_ANY_ENCODED_POLICY; } - public ParserDefinition getParserDefinition(Project project) { + public ParserDefinition getParserDefinition() { return new XMLParserDefinition(); } } diff --git a/source/com/intellij/psi/impl/DebugUtil.java b/source/com/intellij/psi/impl/DebugUtil.java index c5848aee3165..17546c8bae19 100644 --- a/source/com/intellij/psi/impl/DebugUtil.java +++ b/source/com/intellij/psi/impl/DebugUtil.java @@ -1,6 +1,8 @@ package com.intellij.psi.impl; +import com.intellij.lang.ASTNode; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.util.UserDataHolderBase; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; @@ -11,7 +13,6 @@ import com.intellij.psi.impl.source.parsing.ChameleonTransforming; import com.intellij.psi.impl.source.tree.*; import com.intellij.util.ArrayUtil; import com.intellij.util.CharTable; -import com.intellij.lang.ASTNode; /** * @@ -44,6 +45,24 @@ public class DebugUtil { return buffer.toString(); } + //TODO: remove this method. Necessary for debug purposes while we do not have PsiElement's for javascript + public static PsiElement treeElementToPsi(ASTNode element) { + ProgressManager.getInstance().checkCanceled(); + + if (element == null) return null; + + if (element instanceof PsiElement) { + return (PsiElement)element; + } + else if (element instanceof RepositoryTreeElement) { + return RepositoryElementsManager.getOrFindPsiElement((RepositoryTreeElement)element); + } + else { + PsiElement psiElement = element.getUserData(TreeElement.PSI_ELEMENT_KEY); + return psiElement; + } + } + private static void treeToBuffer(StringBuffer buffer, ASTNode root, int indent, boolean skipWhiteSpaces) { if (skipWhiteSpaces && root.getElementType() == ElementType.WHITE_SPACE) return; @@ -51,7 +70,13 @@ public class DebugUtil { buffer.append(' '); } if (root instanceof CompositeElement) { - buffer.append(SourceTreeToPsiMap.treeElementToPsi(root).toString()); + final PsiElement psiElement = treeElementToPsi(root); + if (psiElement != null) { + buffer.append(psiElement.toString()); + } + else { + buffer.append(root.getElementType().toString()); + } } else { String text = root.getText(); diff --git a/source/com/intellij/psi/impl/PsiElementFactoryImpl.java b/source/com/intellij/psi/impl/PsiElementFactoryImpl.java index ae66a05ee07a..26124a529ddd 100644 --- a/source/com/intellij/psi/impl/PsiElementFactoryImpl.java +++ b/source/com/intellij/psi/impl/PsiElementFactoryImpl.java @@ -615,7 +615,7 @@ public class PsiElementFactoryImpl implements PsiElementFactory { final Project project = manager.getProject(); final CharArrayCharSequence text = new CharArrayCharSequence(chars, startOffset, endOffset); if (fileType instanceof LanguageFileType) { - return ((LanguageFileType)fileType).getLanguage().getParserDefinition(project).createFile(project, name, text); + return ((LanguageFileType)fileType).getLanguage().getParserDefinition().createFile(project, name, text); } return new PsiPlainTextFileImpl(project, name, fileType, text); } diff --git a/source/com/intellij/psi/impl/file/impl/FileManagerImpl.java b/source/com/intellij/psi/impl/file/impl/FileManagerImpl.java index cb8e7543f873..05b5439c862d 100644 --- a/source/com/intellij/psi/impl/file/impl/FileManagerImpl.java +++ b/source/com/intellij/psi/impl/file/impl/FileManagerImpl.java @@ -348,7 +348,7 @@ public class FileManagerImpl implements FileManager { final Project project = myManager.getProject(); if (fileType instanceof LanguageFileType) { final Language language = ((LanguageFileType)fileType).getLanguage(); - return language.getParserDefinition(project).createFile(project, vFile); + return language.getParserDefinition().createFile(project, vFile); } if (fileType instanceof JavaClassFileType) { diff --git a/source/com/intellij/psi/impl/source/PsiFileImpl.java b/source/com/intellij/psi/impl/source/PsiFileImpl.java index 17cec5698515..827517572568 100644 --- a/source/com/intellij/psi/impl/source/PsiFileImpl.java +++ b/source/com/intellij/psi/impl/source/PsiFileImpl.java @@ -54,16 +54,24 @@ public abstract class PsiFileImpl extends NonSlaveRepositoryPsiElement implement IElementType contentElementType, String name, CharSequence text) { - super((PsiManagerImpl)PsiManager.getInstance(project), (RepositoryTreeElement)Factory.createCompositeElement(elementType)); + this(project, (FileElement)Factory.createCompositeElement(elementType), elementType, contentElementType, name); + final FileElement parent = getTreeElement(); + char[] chars = CharArrayUtil.fromSequence(text); + TreeElement contentElement = createContentLeafElement(chars, 0, text.length(), parent.getCharTable()); + TreeUtil.addChildren(parent, contentElement); + } + + protected PsiFileImpl(Project project, + FileElement fileElement, + IElementType elementType, + IElementType contentElementType, + String name) { + super((PsiManagerImpl)PsiManager.getInstance(project), fileElement); LOG.assertTrue(name != null); myName = name; myFile = null; myElementType = elementType; myContentElementType = contentElementType; - final FileElement parent = getTreeElement(); - char[] chars = CharArrayUtil.fromSequence(text); - TreeElement contentElement = createContentLeafElement(chars, 0, text.length(), parent.getCharTable()); - TreeUtil.addChildren(parent, contentElement); myModificationStamp = LocalTimeCounter.currentTime(); } diff --git a/source/com/intellij/psi/impl/source/SourceTreeToPsiMap.java b/source/com/intellij/psi/impl/source/SourceTreeToPsiMap.java index 87948841502f..6c3a8296a78e 100644 --- a/source/com/intellij/psi/impl/source/SourceTreeToPsiMap.java +++ b/source/com/intellij/psi/impl/source/SourceTreeToPsiMap.java @@ -1,12 +1,13 @@ package com.intellij.psi.impl.source; +import com.intellij.lang.ASTNode; +import com.intellij.lang.Language; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressManager; import com.intellij.psi.PsiElement; import com.intellij.psi.impl.RepositoryElementsManager; import com.intellij.psi.impl.source.tree.RepositoryTreeElement; import com.intellij.psi.impl.source.tree.TreeElement; -import com.intellij.lang.ASTNode; public class SourceTreeToPsiMap { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.SourceTreeToPsiMap"); @@ -23,9 +24,15 @@ public class SourceTreeToPsiMap { return RepositoryElementsManager.getOrFindPsiElement((RepositoryTreeElement)element); } else { + //TODO!!! PsiElement psiElement = element.getUserData(TreeElement.PSI_ELEMENT_KEY); if (psiElement != null) return psiElement; - + final Language lang = element.getElementType().getLanguage(); + if (lang != null) { + psiElement = lang.getParserDefinition().createElement(element); + element.putUserData(TreeElement.PSI_ELEMENT_KEY, psiElement); + return psiElement; + } LOG.error("Not PsiElement:" + element); return null; } diff --git a/source/com/intellij/psi/impl/source/tree/CompositeElement.java b/source/com/intellij/psi/impl/source/tree/CompositeElement.java index fd821ca8b4dc..a5c4f251c249 100644 --- a/source/com/intellij/psi/impl/source/tree/CompositeElement.java +++ b/source/com/intellij/psi/impl/source/tree/CompositeElement.java @@ -1,5 +1,6 @@ package com.intellij.psi.impl.source.tree; +import com.intellij.lang.ASTNode; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.PsiElement; @@ -12,7 +13,6 @@ import com.intellij.psi.impl.source.tree.java.ReplaceExpressionUtil; import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.TokenSet; import com.intellij.util.CharTable; -import com.intellij.lang.ASTNode; public class CompositeElement extends TreeElement implements Cloneable { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.CompositeElement"); @@ -132,6 +132,14 @@ public class CompositeElement extends TreeElement implements Cloneable { } } + public ASTNode findChildByType(IElementType type) { + return TreeUtil.findChild(this, type); + } + + public ASTNode[] findChildrenByFilter(TokenSet filter) { + return TreeUtil.findChildren(this, filter); + } + public String getText() { return getText(SharedImplUtil.findCharTableByTree(this)); } diff --git a/source/com/intellij/psi/impl/source/tree/LeafElement.java b/source/com/intellij/psi/impl/source/tree/LeafElement.java index a92f39a99653..f99433ad40c8 100644 --- a/source/com/intellij/psi/impl/source/tree/LeafElement.java +++ b/source/com/intellij/psi/impl/source/tree/LeafElement.java @@ -1,12 +1,11 @@ package com.intellij.psi.impl.source.tree; +import com.intellij.lang.ASTNode; import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.TokenSet; import com.intellij.util.CharTable; import com.intellij.util.IncorrectOperationException; import com.intellij.util.text.StringSearcher; -import com.intellij.lang.ASTNode; -import sun.plugin.dom.exception.InvalidStateException; public abstract class LeafElement extends TreeElement { private volatile int myState = 0; // 16 bit for type, 15 bit for state and 1 bit for parentFlag @@ -124,6 +123,14 @@ public abstract class LeafElement extends TreeElement { public abstract int getCharTabIndex(); + public ASTNode findChildByType(IElementType type) { + return null; + } + + public ASTNode[] findChildrenByFilter(TokenSet filter) { + return ASTNode.EMPTY_ARRAY; + } + public ASTNode getFirstChildNode() { return null; } diff --git a/source/com/intellij/psi/impl/source/tree/TreeUtil.java b/source/com/intellij/psi/impl/source/tree/TreeUtil.java index afe4ba42b823..89378a495f5e 100644 --- a/source/com/intellij/psi/impl/source/tree/TreeUtil.java +++ b/source/com/intellij/psi/impl/source/tree/TreeUtil.java @@ -1,14 +1,16 @@ package com.intellij.psi.impl.source.tree; +import com.intellij.lang.ASTNode; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.impl.DebugUtil; import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.TokenSet; import com.intellij.util.CharTable; -import com.intellij.lang.ASTNode; +import java.util.ArrayList; import java.util.HashSet; +import java.util.List; import java.util.Set; public class TreeUtil { @@ -34,6 +36,19 @@ public class TreeUtil { return null; } + public static ASTNode[] findChildren(ASTNode parent, TokenSet types) { + if (DebugUtil.CHECK_INSIDE_ATOMIC_ACTION_ENABLED){ + ApplicationManager.getApplication().assertReadAccessAllowed(); + } + List result = new ArrayList(); + for(ASTNode element = parent.getFirstChildNode(); element != null; element = element.getTreeNext()){ + if (types.isInSet(element.getElementType())) { + result.add(element); + } + } + return result.toArray(new ASTNode[result.size()]); + } + public static ASTNode findChildBackward(ASTNode parent, IElementType type) { if (DebugUtil.CHECK_INSIDE_ATOMIC_ACTION_ENABLED){ ApplicationManager.getApplication().assertReadAccessAllowed();