Type and expression code fragments initial implementation

This commit is contained in:
Alexander Kirillin
2013-04-25 20:42:04 +04:00
parent 6591f54ad5
commit 500a165191
13 changed files with 384 additions and 15 deletions
@@ -148,4 +148,7 @@ public interface JetNodeTypes {
JetNodeType SCRIPT = new JetNodeType("SCRIPT", JetScript.class);
JetNodeType IDE_TEMPLATE_EXPRESSION = new JetNodeType("IDE_TEMPLATE_EXPRESSION", JetIdeTemplate.class);
IFileElementType TYPE_CODE_FRAGMENT = new JetTypeCodeFragmentType();
IFileElementType EXPRESSION_CODE_FRAGMENT = new JetExpressionCodeFragmentType();
}
@@ -19,10 +19,8 @@ package org.jetbrains.jet.lang.parsing;
import com.intellij.lang.ASTNode;
import com.intellij.lang.PsiBuilder;
import com.intellij.lang.PsiParser;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.file.impl.JavaFileManager;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
@@ -53,4 +51,18 @@ public class JetParser implements PsiParser {
}
return psiBuilder.getTreeBuilt();
}
@NotNull
public static ASTNode parseTypeCodeFragment(PsiBuilder psiBuilder) {
JetParsing jetParsing = JetParsing.createForTopLevel(new SemanticWhitespaceAwarePsiBuilderImpl(psiBuilder));
jetParsing.parseTypeCodeFragment();
return psiBuilder.getTreeBuilt();
}
@NotNull
public static ASTNode parseExpressionCodeFragment(PsiBuilder psiBuilder) {
JetParsing jetParsing = JetParsing.createForTopLevel(new SemanticWhitespaceAwarePsiBuilderImpl(psiBuilder));
jetParsing.parseExpressionCodeFragment();
return psiBuilder.getTreeBuilt();
}
}
@@ -16,6 +16,7 @@
package org.jetbrains.jet.lang.parsing;
import com.intellij.extapi.psi.ASTWrapperPsiElement;
import com.intellij.lang.ASTNode;
import com.intellij.lang.LanguageParserDefinitions;
import com.intellij.lang.ParserDefinition;
@@ -25,25 +26,19 @@ import com.intellij.openapi.project.Project;
import com.intellij.psi.FileViewProvider;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.IFileElementType;
import com.intellij.psi.tree.TokenSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetNodeType;
import org.jetbrains.jet.JetNodeTypes;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.stubs.elements.JetStubElementType;
import org.jetbrains.jet.lang.psi.stubs.elements.JetStubElementTypes;
import org.jetbrains.jet.lang.resolve.AnalyzerScriptParameter;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.types.ref.JetTypeName;
import org.jetbrains.jet.lexer.JetLexer;
import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.jet.plugin.JetLanguage;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class JetParserDefinition implements ParserDefinition {
public static final String KTSCRIPT_FILE_SUFFIX = "ktscript";
@@ -96,11 +91,17 @@ public class JetParserDefinition implements ParserDefinition {
@Override
@NotNull
public PsiElement createElement(ASTNode astNode) {
if (astNode.getElementType() instanceof JetStubElementType) {
return ((JetStubElementType) astNode.getElementType()).createPsiFromAst(astNode);
}
IElementType elementType = astNode.getElementType();
return ((JetNodeType) astNode.getElementType()).createPsi(astNode);
if (elementType instanceof JetStubElementType) {
return ((JetStubElementType) elementType).createPsiFromAst(astNode);
}
else if (elementType == JetNodeTypes.TYPE_CODE_FRAGMENT || elementType == JetNodeTypes.EXPRESSION_CODE_FRAGMENT) {
return new ASTWrapperPsiElement(astNode);
}
else {
return ((JetNodeType) elementType).createPsi(astNode);
}
}
@Override
@@ -98,6 +98,30 @@ public class JetParsing extends AbstractJetParsing {
fileMarker.done(JET_FILE);
}
void parseTypeCodeFragment() {
PsiBuilder.Marker marker = mark();
parseTypeRef();
while (!eof()) {
error("unexpected symbol");
advance();
}
marker.done(TYPE_CODE_FRAGMENT);
}
void parseExpressionCodeFragment() {
PsiBuilder.Marker marker = mark();
myExpressionParsing.parseExpression();
while (!eof()) {
error("unexpected symbol");
advance();
}
marker.done(EXPRESSION_CODE_FRAGMENT);
}
void parseScript() {
PsiBuilder.Marker fileMarker = mark();
@@ -0,0 +1,71 @@
/*
* Copyright 2010-2013 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 org.jetbrains.jet.lang.psi;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiManagerEx;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.tree.IElementType;
import com.intellij.testFramework.LightVirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.plugin.JetFileType;
public class JetCodeFragmentImpl extends JetFile implements PsiCodeFragment {
protected PsiElement context;
private GlobalSearchScope resolveScope;
public JetCodeFragmentImpl(Project project, String name, CharSequence text, IElementType elementType, PsiElement context) {
super(((PsiManagerEx) PsiManager.getInstance(project)).getFileManager().createFileViewProvider(
new LightVirtualFile(name, JetFileType.INSTANCE, text), true));
((SingleRootFileViewProvider)getViewProvider()).forceCachedPsi(this);
init(TokenType.CODE_FRAGMENT, elementType);
this.context = context;
}
@Override
public void forceResolveScope(GlobalSearchScope scope) {
resolveScope = scope;
}
@Override
public GlobalSearchScope getForcedResolveScope() {
return resolveScope;
}
@Override
public boolean isPhysical() {
return true;
}
@Override
public boolean isValid() {
return true;
}
@Override
public PsiElement getContext() {
return context;
}
@Override
@NotNull
public GlobalSearchScope getResolveScope() {
if (resolveScope != null) return resolveScope;
return super.getResolveScope();
}
}
@@ -0,0 +1,26 @@
/*
* Copyright 2010-2013 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 org.jetbrains.jet.lang.psi;
import com.intellij.psi.PsiCodeFragment;
import org.jetbrains.annotations.Nullable;
public interface JetExpressionCodeFragment extends PsiCodeFragment {
@Nullable
JetExpression getExpression();
}
@@ -0,0 +1,39 @@
/*
* Copyright 2010-2013 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 org.jetbrains.jet.lang.psi;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.JetNodeTypes;
public class JetExpressionCodeFragmentImpl extends JetCodeFragmentImpl implements JetExpressionCodeFragment {
public JetExpressionCodeFragmentImpl(
Project project,
String name,
CharSequence text,
PsiElement context
) {
super(project, name, text, JetNodeTypes.EXPRESSION_CODE_FRAGMENT, context);
}
@Override
@Nullable
public JetExpression getExpression() {
return findChildByClass(JetExpression.class);
}
}
@@ -0,0 +1,49 @@
/*
* Copyright 2010-2013 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 org.jetbrains.jet.lang.psi;
import com.intellij.lang.ASTNode;
import com.intellij.lang.Language;
import com.intellij.lang.PsiBuilder;
import com.intellij.lang.PsiBuilderFactory;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.parsing.JetParser;
import org.jetbrains.jet.lang.psi.stubs.elements.JetFileElementType;
public class JetExpressionCodeFragmentType extends JetFileElementType {
private static final String NAME = "jet.EXPRESSION_CODE_FRAGMENT";
public JetExpressionCodeFragmentType() {
super(NAME);
}
@Override
public String getExternalId() {
return NAME;
}
@Override
protected ASTNode doParseContents(@NotNull ASTNode chameleon, @NotNull PsiElement psi) {
Project project = psi.getProject();
Language languageForParser = getLanguageForParser(psi);
PsiBuilder builder = PsiBuilderFactory.getInstance().createBuilder(project, chameleon, null, languageForParser, chameleon.getChars());
return JetParser.parseExpressionCodeFragment(builder);
}
}
@@ -246,4 +246,12 @@ public class JetPsiFactory {
return assignment;
}
public static JetTypeCodeFragment createTypeCodeFragment(Project project, String text, PsiElement context) {
return new JetTypeCodeFragmentImpl(project, "fragment.kt", text, context);
}
public static JetExpressionCodeFragment createExpressionCodeFragment(Project project, String text, PsiElement context) {
return new JetExpressionCodeFragmentImpl(project, "fragment.kt", text, context);
}
}
@@ -0,0 +1,26 @@
/*
* Copyright 2010-2013 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 org.jetbrains.jet.lang.psi;
import com.intellij.psi.PsiCodeFragment;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.types.JetType;
public interface JetTypeCodeFragment extends PsiCodeFragment {
@Nullable
JetType getType();
}
@@ -0,0 +1,58 @@
/*
* Copyright 2010-2013 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 org.jetbrains.jet.lang.psi;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.JetNodeTypes;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import org.jetbrains.jet.lexer.JetTokens;
public class JetTypeCodeFragmentImpl extends JetCodeFragmentImpl implements JetTypeCodeFragment {
public JetTypeCodeFragmentImpl(Project project, String name, CharSequence text, PsiElement context) {
super(project, name, text, JetNodeTypes.TYPE_CODE_FRAGMENT, context);
}
@Nullable
@Override
public JetType getType() {
JetType type = null;
for (PsiElement child : getChildren()) {
IElementType elementType = child.getNode().getElementType();
if (elementType == JetNodeTypes.TYPE_CODE_FRAGMENT) {
for (PsiElement grChild : child.getChildren()) {
if (grChild instanceof JetTypeReference) {
if (!grChild.getText().isEmpty())
//TODO return the actual type
type = KotlinBuiltIns.getInstance().getAnyType();
}
else if (!JetTokens.WHITE_SPACE_OR_COMMENT_BIT_SET.contains(elementType))
return null;
}
}
else if (!JetTokens.WHITE_SPACE_OR_COMMENT_BIT_SET.contains(elementType))
return null;
}
return type;
}
}
@@ -0,0 +1,48 @@
/*
* Copyright 2010-2013 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 org.jetbrains.jet.lang.psi;
import com.intellij.lang.ASTNode;
import com.intellij.lang.Language;
import com.intellij.lang.PsiBuilder;
import com.intellij.lang.PsiBuilderFactory;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.parsing.JetParser;
import org.jetbrains.jet.lang.psi.stubs.elements.JetFileElementType;
public class JetTypeCodeFragmentType extends JetFileElementType {
private static final String NAME = "jet.TYPE_CODE_FRAGMENT";
public JetTypeCodeFragmentType() {
super(NAME);
}
@Override
public String getExternalId() {
return NAME;
}
@Override
protected ASTNode doParseContents(@NotNull ASTNode chameleon, @NotNull PsiElement psi) {
Project project = psi.getProject();
Language languageForParser = getLanguageForParser(psi);
PsiBuilder builder = PsiBuilderFactory.getInstance().createBuilder(project, chameleon, null, languageForParser, chameleon.getChars());
return JetParser.parseTypeCodeFragment(builder);
}
}
@@ -26,6 +26,7 @@ import com.intellij.psi.stubs.StubInputStream;
import com.intellij.psi.stubs.StubOutputStream;
import com.intellij.psi.tree.IStubFileElementType;
import com.intellij.util.io.StringRef;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.parsing.JetParser;
import org.jetbrains.jet.lang.psi.stubs.PsiJetFileStub;
@@ -41,6 +42,10 @@ public class JetFileElementType extends IStubFileElementType<PsiJetFileStub> {
super("jet.FILE", JetLanguage.INSTANCE);
}
protected JetFileElementType(@NonNls String debugName) {
super(debugName, JetLanguage.INSTANCE);
}
@Override
public StubBuilder getBuilder() {
return new JetFileStubBuilder();
@@ -79,7 +84,6 @@ public class JetFileElementType extends IStubFileElementType<PsiJetFileStub> {
return parser.parse(this, builder, psi.getContainingFile()).getFirstChildNode();
}
@Override
public void indexStub(PsiJetFileStub stub, IndexSink sink) {
StubIndexServiceFactory.getInstance().indexFile(stub, sink);