Skip to content

Commit

Permalink
Merge pull request #1198 from artbear/annotations-method-symbol-1115
Browse files Browse the repository at this point in the history
Директивы компиляции и аннотации в MethodSymbol
  • Loading branch information
nixel2007 authored Jun 9, 2020
2 parents f37f584 + f97f684 commit ef3c961
Show file tree
Hide file tree
Showing 11 changed files with 522 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,15 @@
import com.github._1c_syntax.bsl.languageserver.context.symbol.MethodDescription;
import com.github._1c_syntax.bsl.languageserver.context.symbol.MethodSymbol;
import com.github._1c_syntax.bsl.languageserver.context.symbol.ParameterDefinition;
import com.github._1c_syntax.bsl.languageserver.context.symbol.annotations.Annotation;
import com.github._1c_syntax.bsl.languageserver.context.symbol.annotations.AnnotationKind;
import com.github._1c_syntax.bsl.languageserver.context.symbol.annotations.AnnotationParameterDefinition;
import com.github._1c_syntax.bsl.languageserver.context.symbol.annotations.CompilerDirectiveKind;
import com.github._1c_syntax.bsl.languageserver.utils.Ranges;
import com.github._1c_syntax.bsl.languageserver.utils.Trees;
import com.github._1c_syntax.bsl.parser.BSLParser;
import com.github._1c_syntax.bsl.parser.BSLParserBaseVisitor;
import com.github._1c_syntax.bsl.parser.BSLParserRuleContext;
import com.github._1c_syntax.mdclasses.mdo.MDObjectBase;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.tree.ErrorNode;
Expand All @@ -40,12 +45,17 @@
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

public final class MethodSymbolComputer
extends BSLParserBaseVisitor<ParseTree>
implements Computer<List<MethodSymbol>> {

private static final Set<Integer> SPECIAL_COMPILER_DIRECTIVES_TOKEN_TYPES = Set.of(
BSLParser.ANNOTATION_ATSERVERNOCONTEXT_SYMBOL,
BSLParser.ANNOTATION_ATCLIENTATSERVER_SYMBOL);

private final DocumentContext documentContext;
private final List<MethodSymbol> methods = new ArrayList<>();

Expand Down Expand Up @@ -81,8 +91,9 @@ public ParseTree visitFunction(BSLParser.FunctionContext ctx) {
declaration.subName().getStart(),
declaration.paramList(),
true,
declaration.EXPORT_KEYWORD() != null
);
declaration.EXPORT_KEYWORD() != null,
getCompilerDirective(declaration.compilerDirective()),
getAnnotations(declaration.annotation()));

methods.add(methodSymbol);

Expand Down Expand Up @@ -110,21 +121,69 @@ public ParseTree visitProcedure(BSLParser.ProcedureContext ctx) {
declaration.subName().getStart(),
declaration.paramList(),
false,
declaration.EXPORT_KEYWORD() != null
declaration.EXPORT_KEYWORD() != null,
getCompilerDirective(declaration.compilerDirective()),
getAnnotations(declaration.annotation())
);

methods.add(methodSymbol);

return ctx;
}

// есть определенные предпочтения при использовании &НаКлиентеНаСервереБезКонтекста в модуле упр.формы
// при ее использовании с другой директивой будет использоваться именно она
// например, порядок 1
//&НаКлиентеНаСервереБезКонтекста
//&НаСервереБезКонтекста
//показывает Сервер в отладчике и доступен серверный объект ТаблицаЗначений
// или порядок 2
//&НаСервереБезКонтекста
//&НаКлиентеНаСервереБезКонтекста
//аналогично
//т.е. порядок этих 2х директив не важен, все равно используется &НаКлиентеНаСервереБезКонтекста.
// проверял на 8.3.15

// есть определенные предпочтения при использовании &НаКлиентеНаСервере в модуле команды
// при ее использовании с другой директивой будет использоваться именно она
// проверял на 8.3.15
// порядок
// 1
// &НаКлиентеНаСервере
// &НаКлиенте
// вызывает клиент при вызове метода с клиента
// вызывает сервер при вызове метода с сервера
// 2
// &НаКлиенте
// &НаКлиентеНаСервере
// вызывает клиент при вызове метода с клиента
// вызывает сервер при вызове метода с сервера

private static Optional<CompilerDirectiveKind> getCompilerDirective(
List<? extends BSLParser.CompilerDirectiveContext> compilerDirectiveContexts
) {
if (compilerDirectiveContexts.isEmpty()) {
return Optional.empty();
}
var tokenType = compilerDirectiveContexts.stream()
.map(compilerDirectiveContext -> compilerDirectiveContext.getStop().getType())
.filter(SPECIAL_COMPILER_DIRECTIVES_TOKEN_TYPES::contains)
.findAny()
.orElseGet(() -> compilerDirectiveContexts.get(0).getStop().getType());

return CompilerDirectiveKind.of(tokenType);

}

private MethodSymbol createMethodSymbol(
TerminalNode startNode,
TerminalNode stopNode,
Token subName,
BSLParser.ParamListContext paramList,
boolean function,
boolean export
boolean export,
Optional<CompilerDirectiveKind> compilerDirective,
List<Annotation> annotations
) {
Optional<MethodDescription> description = createDescription(startNode.getSymbol());
boolean deprecated = description
Expand All @@ -145,6 +204,8 @@ private MethodSymbol createMethodSymbol(
.deprecated(deprecated)
.mdoRef(mdoRef)
.parameters(createParameters(paramList))
.compilerDirectiveKind(compilerDirective)
.annotations(annotations)
.build();
}

Expand Down Expand Up @@ -177,4 +238,54 @@ private static String getParameterName(TerminalNode identifier) {
.map(ParseTree::getText)
.orElse("<UNKNOWN_IDENTIFIER>");
}

private static List<Annotation> getAnnotations(List<? extends BSLParser.AnnotationContext> annotationContext) {
if (annotationContext.isEmpty()) {
return Collections.emptyList();
}
return annotationContext.stream()
.map(annotation -> createAnnotation(
annotation.annotationName(),
annotation.getStop().getType(),
annotation.annotationParams()))
.collect(Collectors.toList());
}

private static Annotation createAnnotation(BSLParser.AnnotationNameContext annotationNameContext, int type,
BSLParser.AnnotationParamsContext annotationParamsContext) {
final List<AnnotationParameterDefinition> params;
if (annotationParamsContext == null) {
params = Collections.emptyList();
} else {
params = annotationParamsContext.annotationParam().stream()
.map(MethodSymbolComputer::getAnnotationParam)
.collect(Collectors.toList());
}

return Annotation.builder()
.name(annotationNameContext.getText())
.kind(AnnotationKind.of(type))
.parameters(params)
.build();
}

private static AnnotationParameterDefinition getAnnotationParam(BSLParser.AnnotationParamContext o) {
var name = Optional.ofNullable(o.annotationParamName())
.map(BSLParserRuleContext::getText)
.orElse("");
var value = Optional.ofNullable(o.constValue())
.map(BSLParserRuleContext::getText)
.map(MethodSymbolComputer::excludeTrailingQuotes)
.orElse("");
var optional = o.constValue() != null;

return new AnnotationParameterDefinition(name, value, optional);
}

private static String excludeTrailingQuotes(String text) {
if (text.length() > 2 && text.charAt(0) == '\"') {
return text.substring(1, text.length() - 1);
}
return text;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
*/
package com.github._1c_syntax.bsl.languageserver.context.symbol;

import com.github._1c_syntax.bsl.languageserver.context.symbol.annotations.Annotation;
import com.github._1c_syntax.bsl.languageserver.context.symbol.annotations.CompilerDirectiveKind;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
Expand Down Expand Up @@ -68,6 +70,11 @@ public class MethodSymbol implements Symbol {
@Builder.Default
List<ParameterDefinition> parameters = new ArrayList<>();

@Builder.Default
Optional<CompilerDirectiveKind> compilerDirectiveKind = Optional.empty();
@Builder.Default
List<Annotation> annotations = new ArrayList<>();

public Optional<RegionSymbol> getRegion() {
return getParent()
.filter(symbol -> symbol instanceof RegionSymbol)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* This file is a part of BSL Language Server.
*
* Copyright © 2018-2020
* Alexey Sosnoviy <labotamy@gmail.com>, Nikita Gryzlov <nixel2007@gmail.com> and contributors
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*
* BSL Language Server is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* BSL Language Server is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with BSL Language Server.
*/
package com.github._1c_syntax.bsl.languageserver.context.symbol.annotations;

import lombok.Builder;
import lombok.Value;

import java.util.ArrayList;
import java.util.List;

/**
* Класс хранит информацию об аннотации.
* См. {@link com.github._1c_syntax.bsl.languageserver.context.symbol.MethodSymbol}
*/
@Value
@Builder
public class Annotation {
String name;
AnnotationKind kind;

@Builder.Default
List<AnnotationParameterDefinition> parameters = new ArrayList<>();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* This file is a part of BSL Language Server.
*
* Copyright © 2018-2020
* Alexey Sosnoviy <labotamy@gmail.com>, Nikita Gryzlov <nixel2007@gmail.com> and contributors
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*
* BSL Language Server is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* BSL Language Server is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with BSL Language Server.
*/
package com.github._1c_syntax.bsl.languageserver.context.symbol.annotations;

import com.github._1c_syntax.bsl.parser.BSLParser;
import lombok.Getter;

import java.util.stream.Stream;

/**
* Класс хранит информацию о виде аннотации.
* См. {@link Annotation}
*/
public enum AnnotationKind {
BEFORE(BSLParser.ANNOTATION_BEFORE_SYMBOL),
AFTER(BSLParser.ANNOTATION_AFTER_SYMBOL),
AROUND(BSLParser.ANNOTATION_AROUND_SYMBOL),
CHANGEANDVALIDATE(BSLParser.ANNOTATION_CHANGEANDVALIDATE_SYMBOL),
CUSTOM(BSLParser.ANNOTATION_CUSTOM_SYMBOL);

@Getter
private final int tokenType;

AnnotationKind(int tokenType) {
this.tokenType = tokenType;
}

public static AnnotationKind of(int tokenType) {
return Stream.of(values())
.filter(annotationKind -> annotationKind.getTokenType() == tokenType)
.findAny().orElse(CUSTOM);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* This file is a part of BSL Language Server.
*
* Copyright © 2018-2020
* Alexey Sosnoviy <labotamy@gmail.com>, Nikita Gryzlov <nixel2007@gmail.com> and contributors
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*
* BSL Language Server is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* BSL Language Server is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with BSL Language Server.
*/
package com.github._1c_syntax.bsl.languageserver.context.symbol.annotations;

import lombok.Value;

/**
* Класс хранит информацию о параметре аннотации.
* См. {@link Annotation}
*/
@Value
public class AnnotationParameterDefinition {
String name;
String value;
boolean optional;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* This file is a part of BSL Language Server.
*
* Copyright © 2018-2020
* Alexey Sosnoviy <labotamy@gmail.com>, Nikita Gryzlov <nixel2007@gmail.com> and contributors
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*
* BSL Language Server is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* BSL Language Server is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with BSL Language Server.
*/
package com.github._1c_syntax.bsl.languageserver.context.symbol.annotations;

import com.github._1c_syntax.bsl.parser.BSLParser;

import java.util.Optional;
import java.util.stream.Stream;

/**
* Класс хранит информацию о директиве компиляции.
* См. {@link com.github._1c_syntax.bsl.languageserver.context.symbol.MethodSymbol}
*/
public enum CompilerDirectiveKind {
AT_SERVER_NO_CONTEXT(BSLParser.ANNOTATION_ATSERVERNOCONTEXT_SYMBOL),
AT_CLIENT_AT_SERVER_NO_CONTEXT(BSLParser.ANNOTATION_ATCLIENTATSERVERNOCONTEXT_SYMBOL),
AT_CLIENT_AT_SERVER(BSLParser.ANNOTATION_ATCLIENTATSERVER_SYMBOL),
AT_CLIENT(BSLParser.ANNOTATION_ATCLIENT_SYMBOL),
AT_SERVER(BSLParser.ANNOTATION_ATSERVER_SYMBOL);

private final int tokenType;

CompilerDirectiveKind(int tokenType) {
this.tokenType = tokenType;
}

public int getTokenType() {
return tokenType;
}

public static Optional<CompilerDirectiveKind> of(int tokenType){
return Stream.of(values())
.filter(compilerDirective -> compilerDirective.getTokenType() == tokenType)
.findAny();
}
}
Loading

0 comments on commit ef3c961

Please sign in to comment.