/*
* Copyright 2013-2016 Sergey Ignatov, Alexander Zolotov, Florin Patan
*
* 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.goide.psi.impl;
import com.goide.GoLanguage;
import com.goide.psi.*;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFileFactory;
import com.intellij.psi.impl.PsiParserFacadeImpl;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@SuppressWarnings("ConstantConditions")
public class GoElementFactory {
private GoElementFactory() {
}
@NotNull
private static GoFile createFileFromText(@NotNull Project project, @NotNull String text) {
return (GoFile)PsiFileFactory.getInstance(project).createFileFromText("a.go", GoLanguage.INSTANCE, text);
}
@NotNull
public static PsiElement createReturnStatement(@NotNull Project project) {
GoFile file = createFileFromText(project, "package main\nfunc _() { return; }");
return PsiTreeUtil.findChildOfType(file, GoReturnStatement.class);
}
@NotNull
public static PsiElement createSelectStatement(@NotNull Project project) {
GoFile file = createFileFromText(project, "package main\nfunc _() { select {\n} }");
return PsiTreeUtil.findChildOfType(file, GoSelectStatement.class);
}
@NotNull
public static PsiElement createIdentifierFromText(@NotNull Project project, String text) {
GoFile file = createFileFromText(project, "package " + text);
return file.getPackage().getIdentifier();
}
@NotNull
public static GoIfStatement createIfStatement(@NotNull Project project,
@NotNull String condition,
@NotNull String thenBranch,
@Nullable String elseBranch) {
String elseText = elseBranch != null ? " else {\n" + elseBranch + "\n}" : "";
GoFile file = createFileFromText(project, "package a; func _() {\n" +
"if " + condition + " {\n" +
thenBranch + "\n" +
"}" + elseText + "\n" +
"}");
return PsiTreeUtil.findChildOfType(file, GoIfStatement.class);
}
@NotNull
public static GoImportDeclaration createEmptyImportDeclaration(@NotNull Project project) {
return PsiTreeUtil.findChildOfType(createFileFromText(project, "package main\nimport (\n\n)"), GoImportDeclaration.class);
}
@NotNull
public static GoImportDeclaration createImportDeclaration(@NotNull Project project, @NotNull String importString,
@Nullable String alias, boolean withParens) {
importString = GoPsiImplUtil.isQuotedImportString(importString) ? importString : StringUtil.wrapWithDoubleQuote(importString);
alias = alias != null ? alias + " " : "";
GoFile file = createFileFromText(project, withParens
? "package main\nimport (\n" + alias + importString + "\n)"
: "package main\nimport " + alias + importString);
return PsiTreeUtil.findChildOfType(file, GoImportDeclaration.class);
}
@NotNull
public static GoImportSpec createImportSpec(@NotNull Project project, @NotNull String importString, @Nullable String alias) {
GoImportDeclaration importDeclaration = createImportDeclaration(project, importString, alias, true);
return ContainerUtil.getFirstItem(importDeclaration.getImportSpecList());
}
@NotNull
public static GoImportString createImportString(@NotNull Project project, @NotNull String importString) {
GoImportSpec importSpec = createImportSpec(project, importString, null);
return importSpec.getImportString();
}
@NotNull
public static PsiElement createNewLine(@NotNull Project project) {
return PsiParserFacadeImpl.SERVICE.getInstance(project).createWhiteSpaceFromText("\n");
}
@NotNull
public static PsiElement createComma(@NotNull Project project) {
return createFileFromText(project, "package foo; var a,b = 1,2").getVars().get(0).getNextSibling();
}
@NotNull
public static GoPackageClause createPackageClause(@NotNull Project project, @NotNull String name) {
return createFileFromText(project, "package " + name).getPackage();
}
@NotNull
public static GoBlock createBlock(@NotNull Project project) {
GoFunctionDeclaration function = ContainerUtil.getFirstItem(createFileFromText(project, "package a; func t() {\n}").getFunctions());
assert function != null : "Impossible situation! Parser is broken.";
return function.getBlock();
}
@NotNull
public static GoStringLiteral createStringLiteral(@NotNull Project project, @NotNull String stringLiteral) {
GoFile f = createFileFromText(project, "package a; var b = " + stringLiteral);
return PsiTreeUtil.getNextSiblingOfType(ContainerUtil.getFirstItem(f.getVars()), GoStringLiteral.class);
}
@NotNull
public static GoSignature createFunctionSignatureFromText(@NotNull Project project, @NotNull String text) {
GoFile file = createFileFromText(project, "package a; func t(" + text + ") {\n}");
return ContainerUtil.getFirstItem(file.getFunctions()).getSignature();
}
@NotNull
public static GoStatement createShortVarDeclarationStatement(@NotNull Project project,
@NotNull String name,
@NotNull GoExpression initializer) {
GoFile file = createFileFromText(project, "package a; func a() {\n " + name + " := " + initializer.getText() + "}");
return PsiTreeUtil.findChildOfType(file, GoSimpleStatement.class);
}
@NotNull
public static GoStatement createShortVarDeclarationStatement(@NotNull Project project,
@NotNull String leftSide,
@NotNull String rightSide) {
GoFile file = createFileFromText(project, "package a; func a() {\n " + leftSide + " := " + rightSide + "}");
return PsiTreeUtil.findChildOfType(file, GoSimpleStatement.class);
}
@NotNull
public static GoRangeClause createRangeClause(@NotNull Project project, @NotNull String leftSide, @NotNull String rightSide) {
GoFile file = createFileFromText(project, "package a; func a() {\n for " + leftSide + " := range " + rightSide + "{\n}\n}");
return PsiTreeUtil.findChildOfType(file, GoRangeClause.class);
}
@NotNull
public static GoRangeClause createRangeClauseAssignment(@NotNull Project project, @NotNull String leftSide, @NotNull String rightSide) {
GoFile file = createFileFromText(project, "package a; func a() {\n for " + leftSide + " = range " + rightSide + "{\n}\n}");
return PsiTreeUtil.findChildOfType(file, GoRangeClause.class);
}
@NotNull
public static GoRecvStatement createRecvStatement(@NotNull Project project, @NotNull String leftSide, @NotNull String rightSide) {
GoFile file = createFileFromText(project, "package a; func a() {\n select { case " + leftSide + " := " + rightSide + ":\n}\n}");
return PsiTreeUtil.findChildOfType(file, GoRecvStatement.class);
}
@NotNull
public static GoRecvStatement createRecvStatementAssignment(@NotNull Project project, @NotNull String left, @NotNull String right) {
GoFile file = createFileFromText(project, "package a; func a() {\n select { case " + left + " = " + right + ":\n}\n}");
return PsiTreeUtil.findChildOfType(file, GoRecvStatement.class);
}
public static GoAssignmentStatement createAssignmentStatement(@NotNull Project project, @NotNull String left, @NotNull String right) {
GoFile file = createFileFromText(project, "package a; func a() {\n " + left + " = " + right + "}");
return PsiTreeUtil.findChildOfType(file, GoAssignmentStatement.class);
}
@NotNull
public static GoDeferStatement createDeferStatement(@NotNull Project project, @NotNull String expressionText) {
GoFile file = createFileFromText(project, "package a; func a() {\n defer " + expressionText + "}");
return PsiTreeUtil.findChildOfType(file, GoDeferStatement.class);
}
@NotNull
public static GoGoStatement createGoStatement(@NotNull Project project, @NotNull String expressionText) {
GoFile file = createFileFromText(project, "package a; func a() {\n go " + expressionText + "}");
return PsiTreeUtil.findChildOfType(file, GoGoStatement.class);
}
@NotNull
public static GoForStatement createForStatement(@NotNull Project project, @NotNull String text) {
GoFile file = createFileFromText(project, "package a; func a() {\n for {\n" + text + "\n}\n}");
return PsiTreeUtil.findChildOfType(file, GoForStatement.class);
}
@NotNull
public static GoExpression createExpression(@NotNull Project project, @NotNull String text) {
GoFile file = createFileFromText(project, "package a; func a() {\n a := " + text + "}");
return PsiTreeUtil.findChildOfType(file, GoExpression.class);
}
@NotNull
public static GoReferenceExpression createReferenceExpression(@NotNull Project project, @NotNull String name) {
GoFile file = createFileFromText(project, "package a; var a = " + name);
return PsiTreeUtil.findChildOfType(file, GoReferenceExpression.class);
}
@NotNull
public static GoSimpleStatement createComparison(@NotNull Project project, @NotNull String text) {
GoFile file = createFileFromText(project, "package a; func a() {\n " + text + "}");
return PsiTreeUtil.findChildOfType(file, GoSimpleStatement.class);
}
@NotNull
public static GoConstDeclaration createConstDeclaration(@NotNull Project project, @NotNull String text) {
GoFile file = createFileFromText(project, "package a; const " + text);
return PsiTreeUtil.findChildOfType(file, GoConstDeclaration.class);
}
@NotNull
public static GoConstSpec createConstSpec(@NotNull Project project, @NotNull String name, @Nullable String type, @Nullable String value) {
GoConstDeclaration constDeclaration = createConstDeclaration(project, prepareVarOrConstDeclarationText(name, type, value));
return ContainerUtil.getFirstItem(constDeclaration.getConstSpecList());
}
@NotNull
public static GoVarDeclaration createVarDeclaration(@NotNull Project project, @NotNull String text) {
GoFile file = createFileFromText(project, "package a; var " + text);
return PsiTreeUtil.findChildOfType(file, GoVarDeclaration.class);
}
@NotNull
public static GoVarSpec createVarSpec(@NotNull Project project, @NotNull String name, @Nullable String type, @Nullable String value) {
GoVarDeclaration varDeclaration = createVarDeclaration(project, prepareVarOrConstDeclarationText(name, type, value));
return ContainerUtil.getFirstItem(varDeclaration.getVarSpecList());
}
@NotNull
private static String prepareVarOrConstDeclarationText(@NotNull String name, @Nullable String type, @Nullable String value) {
type = StringUtil.trim(type);
value = StringUtil.trim(value);
type = StringUtil.isNotEmpty(type) ? " " + type : "";
value = StringUtil.isNotEmpty(value) ? " = " + value : "";
return name + type + value;
}
public static GoTypeList createTypeList(@NotNull Project project, @NotNull String text) {
GoFile file = createFileFromText(project, "package a; func _() (" + text + "){}");
return PsiTreeUtil.findChildOfType(file, GoTypeList.class);
}
public static GoType createType(@NotNull Project project, @NotNull String text) {
GoFile file = createFileFromText(project, "package a; var a " + text);
return PsiTreeUtil.findChildOfType(file, GoType.class);
}
public static PsiElement createLiteralValueElement(@NotNull Project project, @NotNull String key, @NotNull String value) {
GoFile file = createFileFromText(project, "package a; var _ = struct { a string } { " + key + ": " + value + " }");
return PsiTreeUtil.findChildOfType(file, GoElement.class);
}
@NotNull
public static GoTypeDeclaration createTypeDeclaration(@NotNull Project project, @NotNull String name, @NotNull GoType type) {
GoFile file = createFileFromText(project, "package a; type " + name + " " + type.getText());
return PsiTreeUtil.findChildOfType(file, GoTypeDeclaration.class);
}
}