Skip to content

Commit

Permalink
Add EOF linebreak
Browse files Browse the repository at this point in the history
  • Loading branch information
matkoch committed Mar 29, 2023
1 parent de46a9f commit 13eda31
Show file tree
Hide file tree
Showing 132 changed files with 132 additions and 132 deletions.
2 changes: 1 addition & 1 deletion topics/Architecture/Architecture_Overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,4 @@ This is where support for Live Templates, ReSharper's snippet-based code generat

### Refactorings

ReSharper's support for [Refactoring](Refactoring.md) is contained here. These assemblies contain the necessary base classes in order to create and execute your own refactoring workflows.
ReSharper's support for [Refactoring](Refactoring.md) is contained here. These assemblies contain the necessary base classes in order to create and execute your own refactoring workflows.
2 changes: 1 addition & 1 deletion topics/CustomLanguages/BuildingPsiTree.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,4 @@ The parser implements the `IParser` interface, and is usually generated from a `

A handwritten parser is useful if the language is extremely simple, or if the language is too complex to be represented in a `.psi` file easily. Another reason for using a handwritten parser is if the language is a superset of another language. For example, TypeScript files are a superset of JavaScript files, so can reuse parts of the parser, for statements, method definitions, etc. A hand rolled parser makes it easier to call into parts of another parser.

ReSharper supports incremental re-parsing, whereby only the affected subtree is replaced, rather than having to reparse the whole file. This requires special block nodes that know how to reparse their own content.
ReSharper supports incremental re-parsing, whereby only the affected subtree is replaced, rather than having to reparse the whole file. This requires special block nodes that know how to reparse their own content.
2 changes: 1 addition & 1 deletion topics/CustomLanguages/CustomLanguages_Overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -281,4 +281,4 @@ protected override bool Skip(TokenNodeType tokenType)
{
return MyLanguageService.TokensToSkip[tokenType];
}
```
```
2 changes: 1 addition & 1 deletion topics/CustomLanguages/HtmlLike.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,4 @@ ReSharper provides the following:

* Language registration - `HtmlLanguageService` to act as a base class for the [PSI Language Service](PsiLanguageDefinition.md).
* [Lexing](HtmlLike_Lexing.md) - `HtmlCompoundLexer` and `HtmlCompoundIncrementalLexer` which interleaves lexing the custom parts of the language with standard HTML.
* Parsing - `IWebTreeBuilder` and the `WebTreeBuilder` base class to parse the mix of custom and traditional HTML syntax. HTML-like languages use custom written parsers rather than parsers generated with `PsiGen` and `.psi` files. This also means that the PSI element types are also generated by hand - the syntax of HTML and its derived languages is small and regular enough that this is possible.
* Parsing - `IWebTreeBuilder` and the `WebTreeBuilder` base class to parse the mix of custom and traditional HTML syntax. HTML-like languages use custom written parsers rather than parsers generated with `PsiGen` and `.psi` files. This also means that the PSI element types are also generated by hand - the syntax of HTML and its derived languages is small and regular enough that this is possible.
2 changes: 1 addition & 1 deletion topics/CustomLanguages/HtmlLike/ExtendingHtml.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ This means that HTML files are treated as "Angular HTML" files, and are now asso

This does not affect compound lexers - typically, they pass in a new instance of `HtmlLexerFactory`. To get Angular support in a custom HTML-like language, pass in an instance of `Angular2HtmlLexerFactory`.

In order to match ReSharper behaviour, the custom language should check to see if Angular support is enabled, by taking in an instance of the `AngularIsEnabledProvider` shell component, and comparing the `GlobalAngularLevel` to `AngularLevel.None`.
In order to match ReSharper behaviour, the custom language should check to see if Angular support is enabled, by taking in an instance of the `AngularIsEnabledProvider` shell component, and comparing the `GlobalAngularLevel` to `AngularLevel.None`.
2 changes: 1 addition & 1 deletion topics/CustomLanguages/HtmlLike/HtmlLike_Lexing.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,4 @@ public short NStates { get { return (short) yy_state_dtrans.Length; } }
<div class="@MyClass" />
```

This could be implemented as a `RAW_HTML` token that spans from the start of the element up to the `@` symbol - `<div class="`. The HTML lexer will then return tokens for the opening bracket, the element, the attribute name, the equals, the quote symbol and then relinquish control to the base lexer, which will return tokens for the expression - `@MyClass`. It can then return `RAW_HTML` for the closing quotes and the closing element bracket - `" />`. Because the HTML lexer state is preserved, HTML lexing will continue as expected, and the HTML tokens are correct.
This could be implemented as a `RAW_HTML` token that spans from the start of the element up to the `@` symbol - `<div class="`. The HTML lexer will then return tokens for the opening bracket, the element, the attribute name, the equals, the quote symbol and then relinquish control to the base lexer, which will return tokens for the expression - `@MyClass`. It can then return `RAW_HTML` for the closing quotes and the closing element bracket - `" />`. Because the HTML lexer state is preserved, HTML lexing will continue as expected, and the HTML tokens are correct.
2 changes: 1 addition & 1 deletion topics/CustomLanguages/InjectedPsi.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ Alternatively, for primary PSI files you can replace these calls to `GetNonInjec

```csharp
var file = process.SourceFile.GetNonInjectedPsiFile<CSharpLanguage>();
```
```
2 changes: 1 addition & 1 deletion topics/CustomLanguages/Parsing/Lexing/CachingLexers.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ If the underlying lexer does not implement `IIncrementalLexer`, the `Rescan` met

If a parser supports incremental parsing, it should use an instance of `CachingLexer` as its lexer - the `ToCachingLexer` extension method on `ILexer` will create this for you.

More detail is provided in the section on incremental parsing.
More detail is provided in the section on incremental parsing.
2 changes: 1 addition & 1 deletion topics/CustomLanguages/Parsing/Lexing/CsLex.md
Original file line number Diff line number Diff line change
Expand Up @@ -327,4 +327,4 @@ CsLex is Copyright 2000 by Brad Merrill

Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the name of the authors or their employers not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission.

The authors and their employers disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall the authors or their employers be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software.
The authors and their employers disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall the authors or their employers be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software.
2 changes: 1 addition & 1 deletion topics/CustomLanguages/Parsing/Lexing/FilteringLexers.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,4 @@ When the parser builds a PSI tree, the resulting tree needs to cover the entire

After parsing with a filtering lexer, a *missing token inserter* must be run to reinsert these missing tokens. The `MissingTokenInserterBase` abstract base class provides a base implementation, by walking the PSI tree and calling the `ProcessLeafElement` abstract method for each leaf element.

More details can be found in the Parsers section.
More details can be found in the Parsers section.
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,4 @@ These interfaces expose the lexer state as a `uint` value. If the lexer is built

The `IIncrementalLexer` interface has a `Start` method, which allows the lexer to start from an arbitrary point in the text buffer, without having to parse the preceding part of the file first. It takes a start and end offset, and also the `uint` state value returned from `ILexerEx.LexerStateEx`. These values will have been cached from a previous scan of the text buffer. The `TokenBuffer` and `CachingLexer` classes implement this.

More details are in the section on incremental parsing.
More details are in the section on incremental parsing.
2 changes: 1 addition & 1 deletion topics/CustomLanguages/Parsing/Lexing/LexerFactories.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ This class is usually trivial to implement, simply returning a new instance of a
>
{type="note"}

The `IBuffer` interface is an abstraction of a text based buffer that a lexer uses to get the contents of the file (persistent or in-memory). See the guide on [Text Buffers](TextBuffers.md) for more details.
The `IBuffer` interface is an abstraction of a text based buffer that a lexer uses to get the contents of the file (persistent or in-memory). See the guide on [Text Buffers](TextBuffers.md) for more details.
2 changes: 1 addition & 1 deletion topics/CustomLanguages/Parsing/Lexing/LexerUtil.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@ public static class LexerUtil
public static int AdvanceWhile<TLexer>(this TLexer lexer, TokenNodeType skipToken);
public static int AdvanceWhile<TLexer>(this TLexer lexer, NodeTypeSet skipTokens);
}
```
```
2 changes: 1 addition & 1 deletion topics/CustomLanguages/Parsing/Lexing/Lexing_Testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,4 @@ protected override void WriteToken(TextWriter writer, ILexer lexer)
{
writer.WriteLine("{0} [{1}-{2}]", lexer.TokenType, lexer.TokenStart, lexer.TokenEnd);
}
```
```
2 changes: 1 addition & 1 deletion topics/CustomLanguages/Parsing/Lexing/Tao.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,4 @@ Languages frequently declare keywords that are essentially reserved identifiers.

## Write tests

The easiest way to make sure the lexer is correct is to [write tests](Lexing_Testing.md). Include cases that match as well as cases that don't match. Make sure to test for error conditions such as unterminated constructs.
The easiest way to make sure the lexer is correct is to [write tests](Lexing_Testing.md). Include cases that match as well as cases that don't match. Make sure to test for error conditions such as unterminated constructs.
2 changes: 1 addition & 1 deletion topics/CustomLanguages/Parsing/Lexing/TextBuffers.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,4 +112,4 @@ public struct TextRange : IEquatable<TextRange>

public TextRange UpdateRange(int changeStartOffset, int oldLength, int newLength, bool greedyToLeft, bool greedyToRight);
}
```
```
2 changes: 1 addition & 1 deletion topics/CustomLanguages/Parsing/Lexing/UtilityClasses.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,4 @@ public partial class MyLexer
}
```

By default, the `LexerDictionary` is case sensitive, but this can be made case insensitive by passing `false` to the constructor.
By default, the `LexerDictionary` is case sensitive, but this can be made case insensitive by passing `false` to the constructor.
2 changes: 1 addition & 1 deletion topics/CustomLanguages/Parsing/NodeTypes.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,4 @@ The string value passed to the constructor is only used for diagnostic purposes

The `BaseNodeType` property is rarely used, but allows one node type to be treated like another node type. It's only used in JavaScript's WinRT support, where a WinRT expression can be treated either as a WinRT expression, or a plain JavaScript expression. For the majority of uses, it can be ignored.

See the sections on [Token Node Types](TokenNodeTypes.md), [Composite Node Types](CompositeNodeTypes.md) and [Creating Node Types](CreatingNodeTypes.md).
See the sections on [Token Node Types](TokenNodeTypes.md), [Composite Node Types](CompositeNodeTypes.md) and [Creating Node Types](CreatingNodeTypes.md).
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,4 @@ See the section on [Creating Node Types](CreatingNodeTypes.md) for an explanatio

The `Create` method will create an `ITreeNode` instance. There is no need to pass any parameters - the position of the element is implied by its predecessor nodes (and cached and invalidated if the tree is altered). Given the start and end offset, it's possible to get the total text for the node and all associated child nodes.

There is also no need to pass details about the content of the node, as this information is made available via child nodes. For example, a node that represents a C# assignment operation will have children that represents the left hand side identifier, the equals sign and the right hand side expression. The left hand side node can have further child nodes to expose qualifications (`this.value = …`) or can be a leaf node that exposes the identifier directly.
There is also no need to pass details about the content of the node, as this information is made available via child nodes. For example, a node that represents a C# assignment operation will have children that represents the left hand side identifier, the equals sign and the right hand side expression. The left hand side node can have further child nodes to expose qualifications (`this.value = …`) or can be a leaf node that exposes the identifier directly.
Original file line number Diff line number Diff line change
Expand Up @@ -123,4 +123,4 @@ There are a couple of minor differences to how token node types are created. Typ

Also, the names of the composite node type classes are created from the rules in the `.psi` grammar, by converting "CamelCase" to "SHOUTING_SNAKE_CASE", and adding `_INTERNAL`. So a rule such as `colorProfileBlock` creates a private nested composite node class called `COLOR_PROFILE_BLOCK_INTERNAL`, which is then exposed as a public static field instance called `COLOR_PROFILE_BLOCK`.

This `psiGen` tool is described in more detail in the section on parsing.
This `psiGen` tool is described in more detail in the section on parsing.
2 changes: 1 addition & 1 deletion topics/CustomLanguages/Parsing/NodeTypes/TokenNodeTypes.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,4 @@ This can be enough for some languages, while others require a more detailed hier

Similarly, the `KeywordTokenNodeType` derives from `FixedTokenNodeType`, and is used for keywords. Again, there is usually no extra functionality, other than to return `true` from `ITokenNodeType.IsKeyword`.

Sometimes, the language will also define a `GenericTokenNodeType`, that is used as a base class for `FixedTokenNodeType`, and to provide a token node type that is neither an identifier, or whitespace, comment, etc. For example, it can be used to create literals, e.g. `new GenericTokenNodeType("INTEGER_LITERAL", 1176, "000")` or `new GenericTokenNodeType("CHARACTER_LITERAL", 1178, "'c'")`, where the numbers are the unique index of the node type, and the string is the token representation, used in `GetSampleText` and `GetDescription`.
Sometimes, the language will also define a `GenericTokenNodeType`, that is used as a base class for `FixedTokenNodeType`, and to provide a token node type that is neither an identifier, or whitespace, comment, etc. For example, it can be used to create literals, e.g. `new GenericTokenNodeType("INTEGER_LITERAL", 1176, "000")` or `new GenericTokenNodeType("CHARACTER_LITERAL", 1178, "'c'")`, where the numbers are the unique index of the node type, and the string is the token representation, used in `GetSampleText` and `GetDescription`.
2 changes: 1 addition & 1 deletion topics/CustomLanguages/Parsing/Parsing.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ All nodes in a ReSharper parse tree implement a common set of interfaces - namel

A custom language can create a parser that will take a lexer as input. It will analyse the tokens produced by the lexer and return a root `IFile` tree node. This node represents the whole of the file, and will have children that represent the structural and semantic constructs of the file (such as class declarations, method declarations, method bodies, statements, expressions, etc.).

The parser can be created either by hand, using the PSI's `TreeBuilder` helper classes, or by using the PsiGen SDK tool to generate a parser from a custom `.psi` file format that describes the grammar. When generating a parser, the PsiGen tool will also generate the classes and interfaces that make up the tree. While it is possible to create these classes by hand, it is usually quicker and more accurate to describe a grammar in a `.psi` file and get the tool to generate them, even if the parser is created by hand. Generating a parser by hand is only recommended if the grammar is difficult to implement in the `.psi` file format, or if the grammar is to be reused and extended, by another language. For example, the TypeScript grammar reuses parts of the JavaScript parser, which makes it a good candidate for writing by hand - the generated parser cannot be extended and reused in this manner. Despite having different implementations, both methods will create efficient parsers, which is required, as a parse tree needs to be updated as a user edits the file.
The parser can be created either by hand, using the PSI's `TreeBuilder` helper classes, or by using the PsiGen SDK tool to generate a parser from a custom `.psi` file format that describes the grammar. When generating a parser, the PsiGen tool will also generate the classes and interfaces that make up the tree. While it is possible to create these classes by hand, it is usually quicker and more accurate to describe a grammar in a `.psi` file and get the tool to generate them, even if the parser is created by hand. Generating a parser by hand is only recommended if the grammar is difficult to implement in the `.psi` file format, or if the grammar is to be reused and extended, by another language. For example, the TypeScript grammar reuses parts of the JavaScript parser, which makes it a good candidate for writing by hand - the generated parser cannot be extended and reused in this manner. Despite having different implementations, both methods will create efficient parsers, which is required, as a parse tree needs to be updated as a user edits the file.
2 changes: 1 addition & 1 deletion topics/CustomLanguages/Parsing/Parsing/Parsing_Testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,4 +117,4 @@ public abstract class AlternativeParserBaseTest<TLanguage> : BaseTestWithSingleP

This will create a parser for the single file in the project, retrieve the `IFile`, and compare it against the `.gold` file. The input file does not require the `{caret}` identifier.

Furthermore, this test will also check that the text of the file matches the text recreated by getting the text of each node in the tree, as well as validating the range of each tree node against the length of its text, further ensuring the tree is correct.
Furthermore, this test will also check that the text of the file matches the text recreated by getting the text of each node in the tree, as well as validating the range of each tree node against the length of its text, further ensuring the tree is correct.
2 changes: 1 addition & 1 deletion topics/CustomLanguages/Parsing/Parsing_Lexing.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ A parser can then analyse this stream of tokens, looking for known patterns, and

This section looks at how ReSharper expects to be able to create a lexer via a [lexer factory](LexerFactories.md), and the lexer itself must [implement the `ILexer` interface](ImplementingLexers.md), and use [text buffers](TextBuffers.md) to access the text block to analyse. This section also takes a look at how to [use the CsLex SDK tool to tokenise a custom language](CsLex.md).

Finally, this section takes a look at a couple of useful features ReSharper uses while parsing - [lexer utility methods](LexerUtil.md), [filtering lexers](FilteringLexers.md), and [caching lexers](CachingLexers.md).
Finally, this section takes a look at a couple of useful features ReSharper uses while parsing - [lexer utility methods](LexerUtil.md), [filtering lexers](FilteringLexers.md), and [caching lexers](CachingLexers.md).
2 changes: 1 addition & 1 deletion topics/CustomLanguages/Registration.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ A custom language can be the primary language of a file, or it can be secondary,

If a file doesn't have a Project Model file type, or a PSI language mapping, it will be represented by `UnknownProjectFileType` and `UnknownLanguage`, respectively.

Once the file type and language definitions are registered, a [Project Model language service](ProjectFileLanguageService.md) is required to act as a bridge between the Project Model and the PSI, to allow mapping between a file extension and the project file type. Finally, a [PSI language service](PsiLanguageService.md) provides access to the lexer and parser, so that the PSI tree can be built.
Once the file type and language definitions are registered, a [Project Model language service](ProjectFileLanguageService.md) is required to act as a bridge between the Project Model and the PSI, to allow mapping between a file extension and the project file type. Finally, a [PSI language service](PsiLanguageService.md) provides access to the lexer and parser, so that the PSI tree can be built.
Loading

0 comments on commit 13eda31

Please sign in to comment.