SlideShare a Scribd company logo
Annotations
Unleashing the power of Java
Danilo De Luca
@danilodeluca
danilo.luca@dextra-sw.com
Luan Nico
@luanpotter
luannico27@gmail.com
Annotations - O que são?
➔Meta documentação do código
Annotations - O que são?
➔Meta documentação do código
@Override
public void toString() { /* ... */ }
Annotations - Default Annotations
@Override
@Deprecated
@SupressWarnings({ "unchecked" /* , ... */ })
@SafeVarargs
@FunctionalInterface
Annotations - Default Annotations
@Override
@Deprecated
@SupressWarnings({ "unchecked" /* , ... */ })
@SafeVarargs -> stackoverflow.com/questions/14231037
@FunctionalInterface
Annotations - Default Annotations
@Override
@Deprecated
@SupressWarnings({ "unchecked" /* , ... */ })
@SafeVarargs -> stackoverflow.com/questions/14231037
@FunctionalInterface -> Java 8 (Consumer, Function, …)
Annotations - Creating Annotations!
Annotations - Creating Annotations!
public @interface MyShinyAnnotation {
/* ... */
}
Annotations - Annotating Annotations
Annotations - Annotating Annotations
@Retention ◀
@Target
@Documented
@Inherited
Annotations - RetentionPolicy
RetentionPolicy.SOURCE
RetentionPolicy.CLASS
RetentionPolicy.RUNTIME
Annotations - RetentionPolicy
RetentionPolicy.SOURCE - @Override
RetentionPolicy.CLASS
RetentionPolicy.RUNTIME
Annotations - RetentionPolicy
RetentionPolicy.SOURCE - @Override
RetentionPolicy.CLASS - bytecode libs
RetentionPolicy.RUNTIME
Annotations - RetentionPolicy
RetentionPolicy.SOURCE - @Override
RetentionPolicy.CLASS - bytecode libs
RetentionPolicy.RUNTIME - @Deprecated
Annotations - Creating Annotations!
@Retention(RetentionPolicy.RUNTIME)
public @interface MyShinyAnnotation {
/* ... */
}
Annotations - Annotating Annotations
@Retention
@Target ◀
@Documented
@Inherited
Annotations - ElementType
ElementType.ANNOTATION_TYPE
ElementType.CONSTRUCTOR
ElementType.FIELD
ElementType.LOCAL_VARIABLE
ElementType.METHOD
ElementType.PACKAGE
ElementType.PARAMETER
ElementType.TYPE
Annotations - ElementType
ElementType.ANNOTATION_TYPE
ElementType.CONSTRUCTOR
ElementType.FIELD
ElementType.LOCAL_VARIABLE
ElementType.METHOD
ElementType.PACKAGE
ElementType.PARAMETER
ElementType.TYPE
ElementType.TYPE_PARAMETER NEW
ElementType.TYPE_USE NEW
Annotations - Creating Annotations!
@Target({ TYPE, METHOD, FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface MyShinyAnnotation {
/* ... */
}
Annotations - Annotating Annotations
@Retention
@Target
@Documented ◀
@Inherited
Annotations - Annotating Annotations
@Retention
@Target
@Documented
@Inherited ◀ [class only]
Annotations - Annotating Annotations
@Retention
@Target
@Documented
@Inherited
@Repeatable ◀ NEW
Annotations - Elements
Annotations - Elements
@Target({ TYPE, METHOD, FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface MyShinyAnnotation {
String value();
int intValue() default 12;
}
Annotations - Elements
@MyShinyAnnotation
@MyShinyAnnotation()
@MyShinyAnnotation(value = "a")
@MyShinyAnnotation("a")
@MyShinyAnnotation(value = "a", intValue = 7)
@MyShinyAnnotation("a", intValue = 7)
Annotations - Elements
@MyShinyAnnotation
@MyShinyAnnotation() : todos os elements são obrigatórios (salvo default)
@MyShinyAnnotation(value = "a")
@MyShinyAnnotation("a")
@MyShinyAnnotation(value = "a", intValue = 7)
@MyShinyAnnotation("a", intValue = 7)
Annotations - Elements
@MyShinyAnnotation
@MyShinyAnnotation() : todos os elements são obrigatórios (salvo default)
@MyShinyAnnotation(value = "a") : ok
@MyShinyAnnotation("a") : ok
@MyShinyAnnotation(value = "a", intValue = 7)
@MyShinyAnnotation("a", intValue = 7)
Annotations - Elements
@MyShinyAnnotation
@MyShinyAnnotation() : todos os elements são obrigatórios (salvo default)
@MyShinyAnnotation(value = "a") : ok
@MyShinyAnnotation("a") : ok
@MyShinyAnnotation(value = "a", intValue = 7) :ok
@MyShinyAnnotation("a", intValue = 7)
Annotations - Elements
@MyShinyAnnotation
@MyShinyAnnotation() : todos os elements são obrigatórios (salvo default)
@MyShinyAnnotation(value = "a") : ok
@MyShinyAnnotation("a") : ok
@MyShinyAnnotation(value = "a", intValue = 7) :ok
@MyShinyAnnotation("a", intValue = 7) : nok
Annotations - Uses
Annotations - Uses
Documentação - Evolução Javadoc
// Author: John Doe
// Date: 3/17/2002
// Current revision: 6
// Last modified: 4/12/2004
// By: Jane Doe
// Reviewers: Alice, Bill, Cindy
public class MyPojo { /* ... */ }
Annotations - Uses
Documentação - Evolução Javadoc
// Author: John Doe
// Date: 3/17/2002
// Current revision: 6
// Last modified: 4/12/2004
// By: Jane Doe
// Reviewers: Alice, Bill, Cindy
public class MyPojo { /* ... */ }
@ClassPreamble(
author = "John Doe",
date = "3/17/2002",
currentRevision = 6,
lastModified = "4/12/2004",
lastModifiedBy = "Jane Doe",
reviewers = { "Alice", "Bob", "Cindy" }
)
public class MyPojo { /* ... */ }
Annotations - Uses
Documentação - Evolução Javadoc
// Author: John Doe
// Date: 3/17/2002
// Current revision: 6
// Last modified: 4/12/2004
// By: Jane Doe
// Reviewers: Alice, Bill, Cindy
public class MyPojo { /* ... */ }
@ClassPreamble(
author = "John Doe",
date = "3/17/2002",
currentRevision = 6,
lastModified = "4/12/2004",
lastModifiedBy = "Jane Doe",
reviewers = { "Alice", "Bob", "Cindy" }
)
public class MyPojo { /* ... */ }
➔ Easily ‘parseable’!
➔ Standardized!
➔ Type safe!*
*Well, sort of…
➔ Required (compile errors)
Annotations - Uses
Solução mais simples...
Annotations - Uses
Solução mais simples...
GIT
Annotations - Uses
Documentação - Casos Reais
Annotations - Uses
Documentação - Casos Reais
@DroolsUsage
@FailingTest
Annotations - Uses
Runtime Analysis
Annotations - Uses
Runtime Analysis
➔ Hibernate, Spring, Drools, yawp.io
Annotations - Uses
Runtime Analysis
➔ Hibernate, Spring, Drools, yawp.io
Annotations over xml hell!
Annotations - Uses
Annotation Preprocessing
Annotations - Uses
Annotation Preprocessing LATER
Annotations - Uses
Documentação
Runtime Analysis
Annotation Preprocessing
Annotations - Limitations
Annotations - Limitations
★ Valid element types
Annotations - Limitations
★ Valid element types
String Primitives
Enums Annotations
Class Arrays of those
Annotations - Limitations
★ Valid element types
String Primitives
Enums Annotations
Class Arrays of those
>> Use enum’s or String’s
➔ Date -> String
➔ Comparator -> ComparatorType [could be a Class here too]
>> Use other annotations to group fields
>> But no generic enum nor annotation! [Enum, Annotation]
Annotations - Limitations
★ Compile-time constant values
Annotations - Limitations
★ Compile-time constant values
@Source(value = "xpto")
public static String randomString() { /* ... */ }
@Source(value = randomString())
public static String readFromFile() { /* ... */ }
@Source(value = readFromFile())
public static String readFromDatabase() { /* ... */ }
@Source(value = readFromDatabase())
Annotations - Limitations
★ Compile-time constant values
@Source(value = "xpto") : ok
public static String randomString() { /* ... */ }
@Source(value = randomString()) : nok
public static String readFromFile() { /* ... */ }
@Source(value = readFromFile()) : nok
public static String readFromDatabase() { /* ... */ }
@Source(value = readFromDatabase()) : nok
Annotations - Limitations
★ Compile-time constant values
@Source(value = "xpto") : ok
static final String myValue = "xpt";
@Source(value = myValue + "o")
static final String myValue = readFromDatabase();
@Source(value = myValue + "o")
static final String[] myValues = { "xpto" };
@Source(value = myValues[0])
Annotations - Limitations
★ Compile-time constant values
@Source(value = "xpto") : ok
static final String myValue = "xpt";
@Source(value = myValue + "o") : ok
static final String myValue = readFromDatabase();
@Source(value = myValue + "o")
static final String[] myValues = { "xpto" };
@Source(value = myValues[0])
Annotations - Limitations
★ Compile-time constant values
@Source(value = "xpto") : ok
static final String myValue = "xpt";
@Source(value = myValue + "o") : ok
static final String myValue = readFromDatabase();
@Source(value = myValue + "o") : nok
static final String[] myValues = { "xpto" };
@Source(value = myValues[0])
Annotations - Limitations
★ Compile-time constant values
@Source(value = "xpto") : ok
static final String myValue = "xpt";
@Source(value = myValue + "o") : ok
static final String myValue = readFromDatabase();
@Source(value = myValue + "o") : nok
static final String[] myValues = { "xpto" };
@Source(value = myValues[0]) : nok
Annotations - Limitations
★ No inheritance
>> Annotate annotations with annotations
@Validator(clazz = Object.class)
public @interface NotNull { /* ... */ }
Annotations - Limitations
★ No inheritance
>> Annotate annotations with annotations
@Validator(clazz = Object.class)
public @interface NotNull { /* ... */ }
>> Extract repeated code to other classes
>> Make broad annotations with specializing optional parameters
New to Java 8
❖ Repeating Annotations
❖ Type Annotations
Repeating Annotations
Repeating Annotations
@Allow(Roles.USER)
@Allow(Roles.ADMIN)
public void process(Data data) { /* … */ }
Repeating Annotations
@Allow({ Roles.USER, Roles.ADMIN })
public void process(Data data) { /* … */ }
Repeating Annotations
@Allow(value = Roles.USER, access = Access.READ_ONLY)
@Allow(value = Roles.ADMIN, access = Access.READ_WRITE)
public void process(Data data) { /* … */ }
Repeating Annotations
@Allows({
@Allow(value = Roles.USER, access = Access.READ_ONLY)
@Allow(value = Roles.ADMIN, access = Access.READ_WRITE)
})
public void process(Data data) { /* … */ }
Repeating Annotations
@Repeatable(Allows.class)
public @interface Allow {
Role value();
Access access();
}
public @interface Allows {
Allow[] value();
}
Repeating Annotations
@Allow(value = Roles.USER, access = Access.READ_ONLY)
@Allow(value = Roles.ADMIN, access = Access.READ_WRITE)
public void process(Data data) { /* … */ }
Type Annotations
Type Annotations
★ ElementType.TYPE_PARAMETER : tipos usados como generics
★ ElementType.TYPE_USE : qualquer menção a um tipo
Type Annotations
★ List<@Numeric String> phones;
★ Map<@NonEmpty String, @Adult Person> peopleByName;
public void test() {
@NotNull String a = "Hi!";
// ….
}
Type Annotations
★ This can be used for several things:
○ Checkers
○ Static code validation
○ Model Validation
Type Annotations
Example!
<dependency>
<groupId>xyz.luan</groupId>
<artifactId>reflection-utils</artifactId>
<version>0.7.1</version>
</dependency>
Annotation Preprocessing
Annotation Preprocessing
➔Etapas adicionais de compilação
controladas via Annotations
➔Exemplo:
◆ projectlombok.org / github.com/rzwitserloot/lombok
◆ FragmentArgs / ButterKnife [android]
Annotation Preprocessor
➔Project Lombok
public class MyBoringModel {
private String field;
public String getField() {
return this.field;
}
}
Annotation Preprocessor
➔Project Lombok
public class MyBoringModel {
@Getter private String field;
}
➔ @Getter, @Setter, @ToString, @EqualsAndHashCode → @Data
➔ @SneakyThrows, @UtilityClass, @Cleanup
➔Muito mais!
➔projectlombok.org/features
Annotation Preprocessing
➔Como funciona?
◆ Preprocessors extend AbstractProcessor
◆ Implementam os métodos usando uma API análoga
a de Reflection
◆ Registram-se no META-INF
◆ javac sobe uma vm e roda os processadores
registrados em turnos
Annotation Preprocessing
➔Na prática
◆ Baixe o jar da biblioteca e coloque no classpath do
javac
Annotation Preprocessing
➔Na prática
◆ ✓ Baixe o jar da biblioteca e coloque no classpath
do javac
Annotation Preprocessing
➔Na prática
◆ ✓ Baixe o jar da biblioteca e coloque no classpath
do javac
◆ Adicione a dependência no maven/gradle/etc
Annotation Preprocessing
➔Na prática
◆ ✓ Baixe o jar da biblioteca e coloque no classpath
do javac
◆ ✓ Adicione a dependência no maven/gradle/etc
Annotation Preprocessing
➔Na prática
◆ ✓ Baixe o jar da biblioteca e coloque no classpath
do javac
◆ ✓ Adicione a dependência no maven/gradle/etc
➔Precisa ser uma lib separada [META-INF]
➔Precisa habilitar annotation preprocessing
em algumas IDEs (javac faz por padrão)
Annotation Preprocessor
➔Possibilidades
◆ Análise de código (dar erros e warnings...)
◆ Gerar métodos, campos, classes, qualquer coisa
➔Limitações
◆ Triggerado por annotations [processamento em
rodadas]
➔“Problemas”
◆ Excessivamente poderoso
Annotation Preprocessor
➔Como fazer?
◆ Exemplo Codigo
Annotation Preprocessing
<dependencies>
<dependency>
<groupId>com.google.auto.service</groupId>
<artifactId>auto-service</artifactId>
<version>1.0-rc4</version>
</dependency>
</dependencies>
Annotation Preprocessing
➔Extremamente poderoso!
◆ With great power comes great responsibility
➔API razoavelmente feia
➔Podemos juntar com Reflection
◆ Preprocess in compile-time
◆ Reflection in run-time
➔Possibilidades são infinitas
Dúvidas?
Danilo De Luca
@danilodeluca
danilo.luca@dextra-sw.com
Luan Nico
@luanpotter
luannico27@gmail.com

More Related Content

PDF
令和最新!SwiftUI+async_awaitで自分はこう設計・実装している!.pdf
PDF
ストリーミングサービス研究グループ
KEY
Eagle fire 1989
PDF
UXとCS(カスタマーサクセス)
PDF
Php unit the-mostunknownparts
PDF
Java Annotation Processing: A Beginner Walkthrough
PDF
PhpUnit - The most unknown Parts
令和最新!SwiftUI+async_awaitで自分はこう設計・実装している!.pdf
ストリーミングサービス研究グループ
Eagle fire 1989
UXとCS(カスタマーサクセス)
Php unit the-mostunknownparts
Java Annotation Processing: A Beginner Walkthrough
PhpUnit - The most unknown Parts

Similar to Java Annotations and Pre-processing (20)

PDF
Php unit the-mostunknownparts
PDF
international PHP2011_Bastian Feder_The most unknown Parts of PHPUnit
PDF
Programming Android Application in Scala.
PDF
55j7
ODP
Ast transformations
PDF
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017
PDF
Play á la Rails
PPT
Core java concepts
PDF
The Swift Compiler and Standard Library
PDF
What's new in PHP 8.0?
PDF
Nikita Popov "What’s new in PHP 8.0?"
PDF
Android Automated Testing
PPTX
Intro to scala
PPT
Core Java Concepts
KEY
Unit testing en iOS @ MobileCon Galicia
PPTX
An introduction to Raku
PDF
Introduction to Scala for JCConf Taiwan
PDF
Terence Barr - jdk7+8 - 24mai2011
PDF
Serializing EMF models with Xtext
PPTX
Introduction to Client-Side Javascript
Php unit the-mostunknownparts
international PHP2011_Bastian Feder_The most unknown Parts of PHPUnit
Programming Android Application in Scala.
55j7
Ast transformations
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017
Play á la Rails
Core java concepts
The Swift Compiler and Standard Library
What's new in PHP 8.0?
Nikita Popov "What’s new in PHP 8.0?"
Android Automated Testing
Intro to scala
Core Java Concepts
Unit testing en iOS @ MobileCon Galicia
An introduction to Raku
Introduction to Scala for JCConf Taiwan
Terence Barr - jdk7+8 - 24mai2011
Serializing EMF models with Xtext
Introduction to Client-Side Javascript
Ad

Recently uploaded (20)

PDF
Shreyas Phanse Resume: Experienced Backend Engineer | Java • Spring Boot • Ka...
PDF
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PDF
Machine learning based COVID-19 study performance prediction
PPTX
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
PPT
“AI and Expert System Decision Support & Business Intelligence Systems”
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
PDF
KodekX | Application Modernization Development
PDF
NewMind AI Weekly Chronicles - August'25 Week I
PPTX
MYSQL Presentation for SQL database connectivity
PDF
Electronic commerce courselecture one. Pdf
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PPT
Teaching material agriculture food technology
PDF
Empathic Computing: Creating Shared Understanding
PPTX
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PDF
Spectral efficient network and resource selection model in 5G networks
PDF
Agricultural_Statistics_at_a_Glance_2022_0.pdf
PDF
Encapsulation_ Review paper, used for researhc scholars
Shreyas Phanse Resume: Experienced Backend Engineer | Java • Spring Boot • Ka...
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
Building Integrated photovoltaic BIPV_UPV.pdf
Mobile App Security Testing_ A Comprehensive Guide.pdf
Machine learning based COVID-19 study performance prediction
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
“AI and Expert System Decision Support & Business Intelligence Systems”
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
KodekX | Application Modernization Development
NewMind AI Weekly Chronicles - August'25 Week I
MYSQL Presentation for SQL database connectivity
Electronic commerce courselecture one. Pdf
Digital-Transformation-Roadmap-for-Companies.pptx
Teaching material agriculture food technology
Empathic Computing: Creating Shared Understanding
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
Spectral efficient network and resource selection model in 5G networks
Agricultural_Statistics_at_a_Glance_2022_0.pdf
Encapsulation_ Review paper, used for researhc scholars
Ad

Java Annotations and Pre-processing

Editor's Notes

  • #2: http://markup.su/highlighter/
  • #3: http://markup.su/highlighter/
  • #4: [DanDan]
  • #5: [DanDan]
  • #6: [DanDan] SafeVarargs-> falar para o compilador que quando usar metodo com bla(T… asd) ignorar o aviso de problema
  • #7: [DanDan] SafeVarargs-> falar para o compilador que quando usar metodo com bla(T… asd) ignorar o aviso de problema
  • #8: [DanDan] FunctionalInterface -> Criacao de uma interface para lambdas Essas são todas as annotations do JDK, exceto as relacionadas à criação de annotations
  • #9: [Luan]
  • #10: [Luan] they are interfaces!
  • #11: [Luan]
  • #12: [Luan]
  • #13: [Luan]
  • #14: [Luan] RetentionPolicy.SOURCE: Discard during the compile. These annotations don't make any sense after the compile has completed, so they aren't written to the bytecode. Example: @Override, @SuppressWarnings Server somente para documentacao, na compilacao sera jogada fora
  • #15: [Luan] RetentionPolicy.CLASS: Discard during class load. Useful when doing bytecode-level post-processing. Somewhat surprisingly, this is the default. Não deixar vc acessar por reflection e runtime e nem por pre-processamento, so serve para libs que altera direto o bytecode
  • #16: [Luan] RetentionPolicy.RUNTIME: Do not discard. The annotation should be available for reflection at runtime. Example: @Deprecated Esta sempre disponivel inclusive em runtime, reflection e preprocessamento.
  • #17: [Luan]
  • #18: [Luan] Target -> Onde pode usar a annotation
  • #19: [Luan] they are interfaces!
  • #20: [Luan] Type = qualquer declaracao de tipo
  • #21: [Luan] import static ElementType!
  • #22: [Luan] Se ela tiver o @Documented no javadoc ela vai continuar la
  • #23: [Luan] Inherited = Herdado, hereditario Se classe pai com @Bla, e bla for @Inherited, seus filhos vao ter essa annotation
  • #24: [Luan] @Repeatable -> poder repetir a msm annotaiton em um uso.
  • #25: [Luan]
  • #26: [Luan] Sao metodos, mas em particular chamamos de elementos
  • #27: [Luan] Quem ai saberia dizer quais funcionam e quais não e pq?
  • #28: [Luan] they are interfaces!
  • #29: [Luan]
  • #30: [Luan]
  • #31: [Luan] Explicar o pq o ultimo não vai dar ce
  • #32: [DanDan]
  • #33: [DanDan]
  • #34: [DanDan]
  • #35: [DanDan]
  • #36: [DanDan]
  • #37: [DanDan] Git serve para resolver o problema da annotation de documentacao.
  • #38: [DanDan]
  • #39: [DanDan] Duas annotation de 100% de documentacao, não sao runtime.
  • #40: [DanDan] Quando usamos as annotations em runtime para definir o comportamento da aplicacao Assim podemos evitar o uso de XMLs
  • #41: [DanDan] Injeccao de dependencias, @Entites,
  • #42: [DanDan] Injeccao de dependencias, @Entites,
  • #43: [DanDan]
  • #44: [DanDan]
  • #45: [DanDan]
  • #46: [DanDan]
  • #47: [DanDan]
  • #48: [DanDan] Type safe limitado a esses seis tipos: String, enums, class, primitivies, annotations, arrays of those Pq inicialmente as annotations deveriam ser usadas para documentacao, Deve usar valores constantes, não temo como usar uma instancia de alguma classe com valor constante. Annotation nunca deve rodar um codigo!
  • #49: [DanDan] Class não pode ser Generics!
  • #50: [DanDan]
  • #51: [DanDan] O valor deve ser uma constante de compilacao, o uso da annotation nunca pode rodar um codigo
  • #52: [DanDan]
  • #53: [DanDan]
  • #54: [DanDan]
  • #55: [DanDan] Pode somar strings entre coisas que sao constatnes
  • #56: [DanDan] Apenasr do array ser static final os elementos dele não sao constantes, em algum lugar fazer myValues[0] = “ASDSDA”
  • #57: [DanDan]
  • #58: [DanDan] Uma annotation não herdar com outra,
  • #59: [Luan]
  • #60: [Luan]
  • #61: [Luan]
  • #62: [Luan]
  • #63: [Luan]
  • #64: [Luan]
  • #65: [Luan]
  • #66: [Luan]
  • #67: [Luan]
  • #68: [Luan] O ElementType.TYPE_PARAMETER indica que a anotação pode ser usada na declaração de tipos, tais como: classes ou métodos com generics ou ainda junto de caracteres coringa em declarações de tipos anônimos. O ElementType.TYPE_USE indica que a anotação pode ser aplicada em qualquer ponto que um tipo é usado, por exemplo em declarações, generics e conversões de tipos (casts).
  • #69: [Luan]
  • #70: [Luan]
  • #71: [DanDan live code]
  • #72: [Luan]
  • #73: [Luan]
  • #74: [Luan]
  • #75: [Luan]
  • #76: [Luan]
  • #77: [Luan]
  • #78: [Luan]
  • #79: [Luan]
  • #80: [Luan]
  • #81: [Luan]
  • #82: [Luan]
  • #83: [Luan]
  • #84: [Luan]
  • #85: [Luan]
  • #87: http://markup.su/highlighter/