configurable script languages

This commit is contained in:
Alex Tkachman
2012-07-29 21:32:53 +03:00
parent 5cda223ce4
commit f8391619a5
11 changed files with 139 additions and 18 deletions
@@ -81,7 +81,7 @@ public class JetCoreEnvironment {
applicationEnvironment.registerFileType(JetFileType.INSTANCE, "kt");
applicationEnvironment.registerFileType(JetFileType.INSTANCE, "kts");
applicationEnvironment.registerFileType(JetFileType.INSTANCE, "ktm");
applicationEnvironment.registerFileType(JetFileType.INSTANCE, JetParser.KTSCRIPT_FILE_SUFFIX); // should be renamed to kts
applicationEnvironment.registerFileType(JetFileType.INSTANCE, JetParserDefinition.KTSCRIPT_FILE_SUFFIX); // should be renamed to kts
applicationEnvironment.registerFileType(JetFileType.INSTANCE, "jet");
applicationEnvironment.registerParserDefinition(new JavaParserDefinition());
applicationEnvironment.registerParserDefinition(new JetParserDefinition());
@@ -30,11 +30,9 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.analyzer.AnalyzeExhaust;
import org.jetbrains.jet.cli.common.CompilerPlugin;
import org.jetbrains.jet.cli.common.CompilerPluginContext;
import org.jetbrains.jet.cli.common.ExitCode;
import org.jetbrains.jet.cli.common.messages.*;
import org.jetbrains.jet.cli.common.util.CompilerPathUtil;
import org.jetbrains.jet.cli.jvm.JVMConfigurationKeys;
import org.jetbrains.jet.cli.jvm.repl.ReplFromTerminal;
import org.jetbrains.jet.codegen.*;
import org.jetbrains.jet.config.CommonConfigurationKeys;
import org.jetbrains.jet.config.CompilerConfiguration;
@@ -48,11 +46,9 @@ import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.plugin.JetMainDetector;
import org.jetbrains.jet.utils.ExceptionUtils;
import org.jetbrains.jet.utils.PathUtil;
import org.jetbrains.jet.utils.Progress;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Collection;
@@ -60,10 +56,6 @@ import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import static org.jetbrains.jet.cli.common.ExitCode.COMPILATION_ERROR;
import static org.jetbrains.jet.cli.common.ExitCode.INTERNAL_ERROR;
import static org.jetbrains.jet.cli.common.ExitCode.OK;
/**
* @author yole
* @author abreslav
@@ -27,7 +27,11 @@ import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
public class JetParser implements PsiParser {
public static final String KTSCRIPT_FILE_SUFFIX = "ktscript";
private JetParserDefinition parserDefinition;
public JetParser(JetParserDefinition parserDefinition) {
this.parserDefinition = parserDefinition;
}
@Override
@NotNull
@@ -39,7 +43,7 @@ public class JetParser implements PsiParser {
@NotNull
public ASTNode parse(IElementType iElementType, PsiBuilder psiBuilder, PsiFile psiFile) {
JetParsing jetParsing = JetParsing.createForTopLevel(new SemanticWhitespaceAwarePsiBuilderImpl(psiBuilder));
if (psiFile.getName().endsWith("." + KTSCRIPT_FILE_SUFFIX)) {
if (parserDefinition.isScript(psiFile)) {
jetParsing.parseScript();
}
else {
@@ -47,5 +51,4 @@ public class JetParser implements PsiParser {
}
return psiBuilder.getTreeBuilt();
}
}
@@ -20,6 +20,7 @@
package org.jetbrains.jet.lang.parsing;
import com.intellij.lang.ASTNode;
import com.intellij.lang.LanguageParserDefinitions;
import com.intellij.lang.ParserDefinition;
import com.intellij.lang.PsiParser;
import com.intellij.lexer.Lexer;
@@ -34,18 +35,39 @@ import org.jetbrains.jet.JetNodeType;
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";
private HashMap<String,JetScriptDefinition> scripts = new HashMap<String, JetScriptDefinition>();
public JetParserDefinition() {
// .ktscript will take parameters explicitly specified on compilation
JetScriptDefinition standardScript = new JetScriptDefinition(".ktscript", Collections.<AnalyzerScriptParameter>emptyList());
addScriptDefinition(standardScript);
//todo: ApplicationManager.getApplication() is null during JetParsingTest setting up
/*if (!ApplicationManager.getApplication().isCommandLine()) {
}*/
}
@NotNull
public static JetParserDefinition getInstance() {
return (JetParserDefinition)LanguageParserDefinitions.INSTANCE.forLanguage(JetLanguage.INSTANCE);
}
@Override
@NotNull
public Lexer createLexer(Project project) {
@@ -54,7 +76,7 @@ public class JetParserDefinition implements ParserDefinition {
@Override
public PsiParser createParser(Project project) {
return new JetParser();
return new JetParser(this);
}
@Override
@@ -99,4 +121,21 @@ public class JetParserDefinition implements ParserDefinition {
public SpaceRequirements spaceExistanceTypeBetweenTokens(ASTNode astNode, ASTNode astNode1) {
return SpaceRequirements.MAY;
}
public JetScriptDefinition findScriptDefinition(PsiFile psiFile) {
String name = psiFile.getName();
for (Map.Entry<String, JetScriptDefinition> e : scripts.entrySet()) {
if(name.endsWith(e.getKey()))
return e.getValue();
}
return null;
}
public boolean isScript(PsiFile psiFile) {
return findScriptDefinition(psiFile) != null;
}
public void addScriptDefinition(@NotNull JetScriptDefinition scriptDefinition) {
scripts.put(scriptDefinition.getExtension(), scriptDefinition);
}
}
@@ -0,0 +1,44 @@
/*
* Copyright 2010-2012 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.parsing;
import org.jetbrains.jet.lang.resolve.AnalyzerScriptParameter;
import java.util.Arrays;
import java.util.List;
public class JetScriptDefinition {
private final String extension;
private final List<AnalyzerScriptParameter> parameters;
public JetScriptDefinition(String extension, List<AnalyzerScriptParameter> scriptParameters) {
this.extension = extension;
parameters = scriptParameters;
}
public JetScriptDefinition(String extension, AnalyzerScriptParameter... scriptParameters) {
this(extension, Arrays.asList(scriptParameters));
}
public List<AnalyzerScriptParameter> getScriptParameters() {
return parameters;
}
public String getExtension() {
return extension;
}
}
@@ -34,6 +34,10 @@ public class AnalyzerScriptParameter {
this.type = type;
}
public AnalyzerScriptParameter(@NotNull String name, @NotNull String type) {
this(Name.identifier(name), JetTypeName.parse(type));
}
@NotNull
public Name getName() {
return name;
@@ -18,9 +18,14 @@ package org.jetbrains.jet.lang.resolve;
import com.google.common.collect.Lists;
import com.intellij.openapi.util.Key;
import com.intellij.psi.util.PsiUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.parsing.JetParserDefinition;
import org.jetbrains.jet.lang.parsing.JetScriptDefinition;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetPsiUtil;
import org.jetbrains.jet.lang.psi.JetScript;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
import org.jetbrains.jet.lang.resolve.name.FqName;
@@ -148,8 +153,15 @@ public class ScriptHeaderResolver {
scope.setImplicitReceiver(descriptor.getImplicitReceiver());
JetFile file = (JetFile) declaration.getContainingFile();
JetScriptDefinition scriptDefinition = JetParserDefinition.getInstance().findScriptDefinition(file);
int index = 0;
for (AnalyzerScriptParameter scriptParameter : topDownAnalysisParameters.getScriptParameters()) {
List<AnalyzerScriptParameter> scriptParameters = !scriptDefinition.getScriptParameters().isEmpty()
? scriptDefinition.getScriptParameters()
: topDownAnalysisParameters.getScriptParameters();
for (AnalyzerScriptParameter scriptParameter : scriptParameters) {
ValueParameterDescriptor parameter = resolveScriptParameter(scriptParameter, index, descriptor);
valueParameters.add(parameter);
scope.addVariableDescriptor(parameter);
@@ -159,5 +171,4 @@ public class ScriptHeaderResolver {
descriptor.setValueParameters(valueParameters);
}
}
}
@@ -27,13 +27,11 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.JetClassOrObject;
import org.jetbrains.jet.lang.psi.JetDeclaration;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetObjectDeclaration;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
import org.jetbrains.jet.lang.types.DependencyClassByQualifiedNameResolver;
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
import javax.inject.Inject;
@@ -0,0 +1,8 @@
// this script expected parameter num : Int
fun fib(n: Int): Int {
val v = if(n < 2) 1 else fib(n-1) + fib(n-2)
return v
}
val result = fib(num)
@@ -21,6 +21,7 @@ import junit.framework.Test;
import junit.framework.TestSuite;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.parsing.JetParser;
import org.jetbrains.jet.lang.parsing.JetParserDefinition;
import java.io.File;
import java.io.FileFilter;
@@ -68,7 +69,7 @@ public abstract class JetTestCaseBuilder {
public static FilenameFilter kotlinFilter = new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(".kt") || name.endsWith("jet") || name.endsWith("." + JetParser.KTSCRIPT_FILE_SUFFIX);
return name.endsWith(".kt") || name.endsWith(".jet") || name.endsWith("." + JetParserDefinition.KTSCRIPT_FILE_SUFFIX);
}
};
@@ -17,8 +17,15 @@
package org.jetbrains.jet.codegen;
import org.jetbrains.jet.ConfigurationKind;
import org.jetbrains.jet.lang.parsing.JetParserDefinition;
import org.jetbrains.jet.lang.parsing.JetScriptDefinition;
import org.jetbrains.jet.lang.resolve.AnalyzerScriptParameter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
/**
* @author Stepan Koltsov
@@ -86,4 +93,18 @@ public class ScriptGenTest extends CodegenTestCase {
blackBoxFile("script/empty.ktscript");
}
public void testLanguage() {
JetParserDefinition.getInstance().addScriptDefinition(new JetScriptDefinition(".lang.kt", new AnalyzerScriptParameter("num","jet.Int")));
loadFile("script/fib.lang.kt");
final Class aClass = loadClass("Script", generateClassesInFile());
try {
Constructor constructor = aClass.getConstructor(int.class);
Field result = aClass.getField("result");
Object script = constructor.newInstance(5);
assertEquals(8,result.get(script));
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
}