-
Notifications
You must be signed in to change notification settings - Fork 524
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #10 from Microsoft/feature/apiupdates
New API updates
- Loading branch information
Showing
21 changed files
with
823 additions
and
1,141 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
/*--------------------------------------------------------- | ||
* Copyright (C) Microsoft Corporation. All rights reserved. | ||
*--------------------------------------------------------*/ | ||
|
||
'use strict'; | ||
|
||
import {TextDocument, Position, CancellationToken, CompletionItem, CompletionItemProvider, CompletionItemKind, Uri} from 'vscode'; | ||
import helper = require('../helpers/suggestSupportHelper'); | ||
import {DOCKER_COMPOSE_KEY_INFO} from './dockerComposeKeyInfo'; | ||
import hub = require('../dockerHubApi'); | ||
|
||
export class DockerComposeCompletionItemProvider implements CompletionItemProvider { | ||
|
||
public triggerCharacters: string[] = []; | ||
public excludeTokens: string[] = []; | ||
|
||
public provideCompletionItems(document: TextDocument, position: Position, token: CancellationToken): Promise<CompletionItem[]> { | ||
var yamlSuggestSupport = new helper.SuggestSupportHelper(); | ||
|
||
// Get the line where intellisense was invoked on (e.g. 'image: u'). | ||
var line = document.lineAt(position.line).text; | ||
|
||
if (line.length === 0) { | ||
// empty line | ||
return Promise.resolve(this.suggestKeys('')); | ||
} | ||
|
||
let range = document.getWordRangeAtPosition(position); | ||
|
||
// Get the text where intellisense was invoked on (e.g. 'u'). | ||
let word = range && document.getText(range) || ''; | ||
|
||
var textBefore = line.substring(0, position.character); | ||
if (/^\s*[\w_]*$/.test(textBefore)) { | ||
// on the first token | ||
return Promise.resolve(this.suggestKeys(word)); | ||
} | ||
|
||
// Matches strings like: 'image: "ubuntu' | ||
var imageTextWithQuoteMatchYaml = textBefore.match(/^\s*image\s*\:\s*"([^"]*)$/); | ||
|
||
if (imageTextWithQuoteMatchYaml) { | ||
var imageText = imageTextWithQuoteMatchYaml[1]; | ||
return yamlSuggestSupport.suggestImages(imageText); | ||
} | ||
|
||
// Matches strings like: 'image: ubuntu' | ||
var imageTextWithoutQuoteMatch = textBefore.match(/^\s*image\s*\:\s*([\w\:\/]*)/); | ||
|
||
if (imageTextWithoutQuoteMatch) { | ||
var imageText = imageTextWithoutQuoteMatch[1]; | ||
return yamlSuggestSupport.suggestImages(imageText); | ||
} | ||
|
||
return Promise.resolve([]); | ||
} | ||
|
||
private suggestKeys(word: string): CompletionItem[] { | ||
return Object.keys(DOCKER_COMPOSE_KEY_INFO).map(ruleName => { | ||
var completionItem = new CompletionItem(ruleName); | ||
completionItem.kind = CompletionItemKind.Keyword; | ||
completionItem.insertText = ruleName + ': '; | ||
completionItem.documentation = DOCKER_COMPOSE_KEY_INFO[ruleName]; | ||
return completionItem; | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
/*--------------------------------------------------------- | ||
* Copyright (C) Microsoft Corporation. All rights reserved. | ||
*--------------------------------------------------------*/ | ||
|
||
// https://docs.docker.com/compose/yml/ | ||
export var DOCKER_COMPOSE_KEY_INFO: { [keyName: string]: string; } = { | ||
'image': ( | ||
"Tag or partial image ID. Can be local or remote - Compose will attempt to pull if it doesn't exist locally." | ||
), | ||
'build': ( | ||
"Path to a directory containing a Dockerfile. When the value supplied is a relative path, it is interpreted as relative to the " + | ||
"location of the yml file itself. This directory is also the build context that is sent to the Docker daemon.\n\n" + | ||
"Compose will build and tag it with a generated name, and use that image thereafter." | ||
), | ||
'command': ( | ||
"Override the default command." | ||
), | ||
'links': ( | ||
"Link to containers in another service. Either specify both the service name and the link alias (`CONTAINER:ALIAS`), or " + | ||
"just the service name (which will also be used for the alias)." | ||
), | ||
'external_links': ( | ||
"Link to containers started outside this `docker-compose.yml` or even outside of Compose, especially for containers that " + | ||
"provide shared or common services. `external_links` follow " + | ||
"semantics similar to `links` when specifying both the container name and the link alias (`CONTAINER:ALIAS`)." | ||
), | ||
'ports': ( | ||
"Expose ports. Either specify both ports (`HOST:CONTAINER`), or just the container port (a random host port will be chosen).\n\n" + | ||
"**Note**: When mapping ports in the `HOST:CONTAINER` format, you may experience erroneous results when using a container port " + | ||
"lower than 60, because YAML will parse numbers in the format `xx:yy` as sexagesimal (base 60). For this reason, we recommend " + | ||
"always explicitly specifying your port mappings as strings." | ||
), | ||
'expose': ( | ||
"Expose ports without publishing them to the host machine - they'll only be accessible to linked services. \n" + | ||
"Only the internal port can be specified." | ||
), | ||
'volumes': ( | ||
"Mount paths as volumes, optionally specifying a path on the host machine (`HOST:CONTAINER`), or an access mode (`HOST:CONTAINER:ro`)." | ||
), | ||
'volumes_from': ( | ||
"Mount all of the volumes from another service or container." | ||
), | ||
'environment': ( | ||
"Add environment variables. You can use either an array or a dictionary.\n\n" + | ||
"Environment variables with only a key are resolved to their values on the machine Compose is running on, which can be helpful for secret or host-specific values." | ||
), | ||
'env_file': ( | ||
"Add environment variables from a file. Can be a single value or a list.\n\n" + | ||
"If you have specified a Compose file with `docker-compose -f FILE`, paths in `env_file` are relative to the directory that file is in.\n\n" + | ||
"Environment variables specified in `environment` override these values." | ||
), | ||
'net': ( | ||
"Networking mode. Use the same values as the docker client `--net` parameter." | ||
), | ||
'pid': ( | ||
"Sets the PID mode to the host PID mode. This turns on sharing between container and the host operating system the PID address space. " + | ||
"Containers launched with this flag will be able to access and manipulate other containers in the bare-metal machine's namespace and vise-versa." | ||
), | ||
'dns': ( | ||
"Custom DNS servers. Can be a single value or a list." | ||
), | ||
'cap_add': ( | ||
"Add or drop container capabilities. See `man 7 capabilities` for a full list." | ||
), | ||
'cap_drop': ( | ||
"Add or drop container capabilities. See `man 7 capabilities` for a full list." | ||
), | ||
'dns_search': ( | ||
"Custom DNS search domains. Can be a single value or a list." | ||
), | ||
'cgroup_parent': ( | ||
"Specify an optional parent cgroup for the container." | ||
), | ||
'container_name': ( | ||
"Specify custom container name, rather than a generated default name." | ||
), | ||
'devices': ( | ||
"List of device mappings. Uses the same format as the `--device` docker client create option." | ||
), | ||
'dockerfile': ( | ||
"Alternate dockerfile. Compose will use an alternate file to build with. Using `dockerfile` together with `image` is not allowed. Attempting to do so results in an error." | ||
), | ||
'extends': ( | ||
"Extend another service, in the current file or another, optionally overriding configuration.\nYou can use `extends` on any service together with other configuration keys. " + | ||
"The `extends` value must be a dictionary defined with a required `service` and an optional `file` key." | ||
), | ||
'extra_hosts': ( | ||
"Add hostname mappings. Use the same values as the docker client `--add-host` parameter." | ||
), | ||
'labels': ( | ||
"Add metadata to containers using Docker labels. You can either use an array or a dictionary.\n" + | ||
"It's recommended that you use reverse-DNS notation to prevent your labels from conflicting with those used by other software." | ||
), | ||
'log_driver': ( | ||
"Specify a logging driver for the service's containers, as with the `--log-driver` option for docker run. The default value is json-file." | ||
), | ||
'log_opt': ( | ||
"Specify logging options with `log_opt` for the logging driver, as with the `--log-opt` option for docker run." | ||
), | ||
'security_opt': ( | ||
"Override the default labeling scheme for each container." | ||
), | ||
'volume_driver': ( | ||
"If you use a volume name (instead of a volume path), you may also specify a `volume_driver`." | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
/*--------------------------------------------------------- | ||
* Copyright (C) Microsoft Corporation. All rights reserved. | ||
*--------------------------------------------------------*/ | ||
|
||
'use strict'; | ||
|
||
import vscode = require('vscode'); | ||
import {Parser, TokenType, IToken} from '../parser'; | ||
|
||
export class DockerComposeParser extends Parser { | ||
constructor() { | ||
var parseRegex = /\:+$/g; | ||
super(parseRegex, /docker\-compose\.yml$/); | ||
} | ||
|
||
parseLine(textLine: vscode.TextLine): IToken[] { | ||
var r: IToken[] = []; | ||
var lastTokenEndIndex = 0, lastPushedToken: IToken = null; | ||
|
||
var emit = (end: number, type: TokenType) => { | ||
if (end <= lastTokenEndIndex) { | ||
return; | ||
} | ||
|
||
if (lastPushedToken && lastPushedToken.type === type) { | ||
// merge with last pushed token | ||
lastPushedToken.endIndex = end; | ||
lastTokenEndIndex = end; | ||
return; | ||
} | ||
|
||
lastPushedToken = { | ||
startIndex: lastTokenEndIndex, | ||
endIndex: end, | ||
type: type | ||
}; | ||
|
||
r.push(lastPushedToken); | ||
lastTokenEndIndex = end; | ||
}; | ||
|
||
var inString = false; | ||
var idx = textLine.firstNonWhitespaceCharacterIndex; | ||
var line = textLine.text; | ||
|
||
for (var i = idx, len = line.length; i < len; i++) { | ||
var ch = line.charAt(i); | ||
|
||
if (inString) { | ||
if (ch === '"' && line.charAt(i - 1) !== '\\') { | ||
inString = false; | ||
emit(i + 1, TokenType.String); | ||
} | ||
|
||
continue; | ||
} | ||
|
||
if (ch === '"') { | ||
emit(i, TokenType.Text); | ||
inString = true; | ||
continue; | ||
} | ||
|
||
if (ch === '#') { | ||
// Comment the rest of the line | ||
emit(i, TokenType.Text); | ||
emit(line.length, TokenType.Comment); | ||
break; | ||
} | ||
|
||
if (ch === ':') { | ||
emit(i + 1, TokenType.Key); | ||
} | ||
|
||
if (ch === ' ' || ch === '\t') { | ||
emit(i, TokenType.Text); | ||
emit(i + 1, TokenType.Whitespace); | ||
} | ||
} | ||
|
||
emit(line.length, TokenType.Text); | ||
return r; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
/*--------------------------------------------------------- | ||
* Copyright (C) Microsoft Corporation. All rights reserved. | ||
*--------------------------------------------------------*/ | ||
|
||
'use strict'; | ||
|
||
import { Range, TextDocument, Position, CancellationToken, HoverProvider, Hover, MarkedString } from 'vscode'; | ||
import parser = require('./parser'); | ||
import hub = require('./dockerHubApi'); | ||
import suggestHelper = require('./helpers/suggestSupportHelper'); | ||
|
||
export class DockerHoverProvider implements HoverProvider { | ||
_parser: parser.Parser; | ||
_keyInfo: { [keyName: string]: string; }; | ||
|
||
// Provide the parser you want to use as well as keyinfo dictionary. | ||
constructor(wordParser: parser.Parser, keyInfo: { [keyName: string]: string; }) { | ||
this._parser = wordParser; | ||
this._keyInfo = keyInfo; | ||
} | ||
|
||
public provideHover(document: TextDocument, position: Position, token: CancellationToken): Thenable<Hover> { | ||
if (!this._parser.isFileSupported(document.fileName)) { | ||
return Promise.resolve(null); | ||
} | ||
|
||
var line = document.lineAt(position.line); | ||
|
||
if (line.text.length === 0) { | ||
return Promise.resolve(null); | ||
} | ||
|
||
var tokens = this._parser.parseLine(line); | ||
return this._computeInfoForLineWithTokens(line.text, tokens, position); | ||
} | ||
|
||
private _computeInfoForLineWithTokens(line: string, tokens: parser.IToken[], position: Position): Promise<Hover> { | ||
var possibleTokens = this._parser.tokensAtColumn(tokens, position.character); | ||
|
||
return Promise.all(possibleTokens.map(tokenIndex => this._computeInfoForToken(line, tokens, tokenIndex))).then((results) => { | ||
return possibleTokens.map((tokenIndex, arrayIndex) => { | ||
return { | ||
startIndex: tokens[tokenIndex].startIndex, | ||
endIndex: tokens[tokenIndex].endIndex, | ||
result: results[arrayIndex] | ||
}; | ||
}); | ||
}).then((results) => { | ||
var r = results.filter(r => !!r.result); | ||
if (r.length === 0) { | ||
return null; | ||
} | ||
|
||
let range = new Range(position.line, r[0].startIndex, position.line, r[0].endIndex); | ||
let hover = new Hover(r[0].result, range); | ||
return hover; | ||
}); | ||
} | ||
|
||
private _computeInfoForToken(line: string, tokens: parser.IToken[], tokenIndex: number): Promise<MarkedString[]> { | ||
// ------------- | ||
// Detect hovering on a key | ||
if (tokens[tokenIndex].type === parser.TokenType.Key) { | ||
var keyName = this._parser.keyNameFromKeyToken(this._parser.tokenValue(line, tokens[tokenIndex])).trim(); | ||
var r = this._keyInfo[keyName]; | ||
if (r) { | ||
return Promise.resolve([r]); | ||
} | ||
} | ||
|
||
// ------------- | ||
// Detect <<image: [["something"]]>> | ||
// Detect <<image: [[something]]>> | ||
var helper = new suggestHelper.SuggestSupportHelper(); | ||
var r2 = helper.getImageNameHover(line, this._parser, tokens, tokenIndex); | ||
if (r2) { | ||
return r2; | ||
} | ||
|
||
return null; | ||
} | ||
} |
Oops, something went wrong.