Skip to content

Commit

Permalink
Validation for fakerjs in kafka file
Browse files Browse the repository at this point in the history
Fixes jlandersen#154

Signed-off-by: azerr <[email protected]>
  • Loading branch information
angelozerr authored and fbricon committed Apr 26, 2021
1 parent 7523059 commit 7191910
Show file tree
Hide file tree
Showing 14 changed files with 570 additions and 83 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ All notable changes to `Tools for Apache Kafka®` are documented in this file.
- Declare key/value formats for CONSUMER in kafka file. See [#112](https://github.com/jlandersen/vscode-kafka/issues/112).
- Declare key/value formats for PRODUCER in kafka file. See [#113](https://github.com/jlandersen/vscode-kafka/issues/113).
- Completion support for property names and values of CONSUMER and PRODUCER blocks. See [#146](https://github.com/jlandersen/vscode-kafka/issues/146).
- Completion support for fakerJS PRODUCER key and value. See [#152](https://github.com/jlandersen/vscode-kafka/issues/152).
- Completion support for FakerJS PRODUCER key and value. See [#152](https://github.com/jlandersen/vscode-kafka/issues/152).
- Completion support for available topics for CONSUMER and PRODUCER blocks. See [#150](https://github.com/jlandersen/vscode-kafka/issues/150).
- Validation support for property names and values of CONSUMER and PRODUCER blocks. See [#152](https://github.com/jlandersen/vscode-kafka/issues/152).
- Validation support for FakerJS PRODUCER key and value. See [#154](https://github.com/jlandersen/vscode-kafka/issues/154).

### Changed
- Renamed extension as `Tools for Apache Kafka®`
Expand Down
6 changes: 5 additions & 1 deletion docs/Producing.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,14 @@ Completion is available for

Validation will help you write valid producers in .kafka files.

Here is an example of value validation:
* here is an example of value validation:

![Empty value](assets/kafka-file-producer-empty-value-validation.png)

* here is an example with FakerJS validation:

![FakerJS validation](assets/kafka-file-producer-fakerjs-validation.png)

## Randomized content

Record content can be randomized by injecting mustache-like placeholders of [faker.js properties](https://github.com/Marak/faker.js#api-methods), like ``{{name.lastName}}`` or ``{{random.number}}``. Some randomized properties can be localized via the `kafka.producers.fakerjs.locale` setting.
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ export function activate(context: vscode.ExtensionContext): KafkaExtensionPartic

// .kafka file related
context.subscriptions.push(
startLanguageClient(clusterSettings, producerCollection, consumerCollection, explorer, context)
startLanguageClient(clusterSettings, workspaceSettings, producerCollection, consumerCollection, explorer, context)
);

context.subscriptions.push(
Expand Down
37 changes: 29 additions & 8 deletions src/kafka-file/kafkaFileClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ import { runSafeAsync } from "./utils/runner";
import { TopicItem } from "../explorer";
import { KafkaModelProvider } from "../explorer/models/kafka";
import { ThrottledDelayer } from "./utils/async";
import { WorkspaceSettings } from "../settings";

export function startLanguageClient(
clusterSettings: ClusterSettings,
workspaceSettings: WorkspaceSettings,
producerCollection: ProducerCollection,
consumerCollection: ConsumerCollection,
modelProvider: KafkaModelProvider,
Expand Down Expand Up @@ -52,13 +54,13 @@ export function startLanguageClient(
});

// Completion
const completion = new KafkaFileCompletionItemProvider(kafkaFileDocuments, languageService, workspaceSettings);
context.subscriptions.push(
vscode.languages.registerCompletionItemProvider(documentSelector,
new KafkaFileCompletionItemProvider(kafkaFileDocuments, languageService),
':', '{', '.'));
vscode.languages.registerCompletionItemProvider(documentSelector, completion, ':', '{', '.')
);

// Validation
const diagnostics = new KafkaFileDiagnostics(kafkaFileDocuments, languageService);
const diagnostics = new KafkaFileDiagnostics(kafkaFileDocuments, languageService, workspaceSettings);
context.subscriptions.push(diagnostics);

// Open / Close document
Expand Down Expand Up @@ -172,15 +174,16 @@ class KafkaFileCompletionItemProvider extends AbstractKafkaFileFeature implement

constructor(
kafkaFileDocuments: LanguageModelCache<KafkaFileDocument>,
languageService: LanguageService
languageService: LanguageService,
private workspaceSettings: WorkspaceSettings
) {
super(kafkaFileDocuments, languageService);
}

provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, context: vscode.CompletionContext): vscode.ProviderResult<vscode.CompletionItem[] | vscode.CompletionList> {
return runSafeAsync(async () => {
const kafkaFileDocument = this.getKafkaFileDocument(document);
return this.languageService.doComplete(document, kafkaFileDocument, position);
return this.languageService.doComplete(document, kafkaFileDocument, this.workspaceSettings.producerFakerJSEnabled, position);
}, new vscode.CompletionList(), `Error while computing code lenses for ${document.uri}`, token);
}

Expand All @@ -190,14 +193,32 @@ class KafkaFileDiagnostics extends AbstractKafkaFileFeature implements vscode.Di

private diagnosticCollection: vscode.DiagnosticCollection;
private delayers?: { [key: string]: ThrottledDelayer<void> };
producerFakerJSEnabled: boolean;

constructor(
kafkaFileDocuments: LanguageModelCache<KafkaFileDocument>,
languageService: LanguageService
languageService: LanguageService,
settings: WorkspaceSettings
) {
super(kafkaFileDocuments, languageService);
this.diagnosticCollection = vscode.languages.createDiagnosticCollection('kafka');
this.delayers = Object.create(null);
this.producerFakerJSEnabled = settings.producerFakerJSEnabled;
settings.onDidChangeSettings(() => {
if (this.producerFakerJSEnabled !== settings.producerFakerJSEnabled) {
this.validateAll();
this.producerFakerJSEnabled = settings.producerFakerJSEnabled;
}
});
// Validate all opened kafka files when vscode is started
this.validateAll();
}

/**
* Validate all opened kafka files.
*/
public validateAll() {
vscode.workspace.textDocuments.forEach(this.triggerValidate, this);
}

delete(textDocument: vscode.TextDocument) {
Expand All @@ -220,7 +241,7 @@ class KafkaFileDiagnostics extends AbstractKafkaFileFeature implements vscode.Di
private doValidate(document: vscode.TextDocument): Promise<void> {
return new Promise<void>((resolve) => {
const kafkaFileDocument = this.getKafkaFileDocument(document);
const diagnostics = this.languageService.doDiagnostics(document, kafkaFileDocument);
const diagnostics = this.languageService.doDiagnostics(document, kafkaFileDocument, this.producerFakerJSEnabled);
this.diagnosticCollection!.set(document.uri, diagnostics);
resolve();
});
Expand Down
5 changes: 3 additions & 2 deletions src/kafka-file/languageservice/kafkaFileLanguageService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,17 +69,18 @@ export interface LanguageService {
*
* @param document the text document.
* @param kafkaFileDocument the parsed AST.
* @param producerFakerJSEnabled true if FakerJS is enabled and false otherwise.
* @param position the position where the completion was triggered.
*/
doComplete(document: TextDocument, kafkaFileDocument: KafkaFileDocument, position: Position): Promise<CompletionList | undefined>;
doComplete(document: TextDocument, kafkaFileDocument: KafkaFileDocument, producerFakerJSEnabled: boolean, position: Position): Promise<CompletionList | undefined>;

/**
* Returns the diagnostics result for the given text document and parsed AST.
*
* @param document the text document.
* @param kafkaFileDocument the parsed AST.
*/
doDiagnostics(document: TextDocument, kafkaFileDocument: KafkaFileDocument): Diagnostic[];
doDiagnostics(document: TextDocument, kafkaFileDocument: KafkaFileDocument, producerFakerJSEnabled : boolean): Diagnostic[];
}

/**
Expand Down
43 changes: 42 additions & 1 deletion src/kafka-file/languageservice/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -380,4 +380,45 @@ const fakerjsAPI = [
{ name: "vehicle.bicycle" }
] as ModelDefinition[];

export const fakerjsAPIModel = new Model(fakerjsAPI);
export interface PartModelProvider {
getPart(name: string) : PartModelProvider | undefined;
}

class PartModel implements PartModelProvider{

private cache = new Map<string, PartModelProvider>();

getPart(name: string) : PartModelProvider | undefined {
return this.cache.get(name);
}

getOrCreate(name: string) : PartModelProvider {
let part = this.getPart(name);
if (!part) {
part = new PartModel();
this.cache.set(name, part);
}
return part;
}
}

class FakerJSModel extends Model implements PartModelProvider {

private root = new PartModel();
constructor(definitions: ModelDefinition[]) {
super(definitions);
definitions.forEach(definition => {
const parts = definition.name.split('.');
let partModel = this.root;
parts.forEach(part => {
partModel = <PartModel> partModel.getOrCreate(part);
});
});
}

getPart(name: string) : PartModelProvider | undefined {
return this.root.getPart(name);
}
}

export const fakerjsAPIModel = new FakerJSModel(fakerjsAPI);
Loading

0 comments on commit 7191910

Please sign in to comment.