22 * Copyright (c) Microsoft Corporation. All rights reserved.
33 * Licensed under the MIT License. See License.txt in the project root for license information.
44 *--------------------------------------------------------------------------------------------*/
5-
65'use strict' ;
76
7+ import * as fs from 'fs' ;
8+ import * as path from 'path' ;
9+
810import PHPCompletionItemProvider from './features/completionItemProvider' ;
911import PHPHoverProvider from './features/hoverProvider' ;
1012import PHPSignatureHelpProvider from './features/signatureHelpProvider' ;
1113import PHPValidationProvider from './features/validationProvider' ;
12- import { ExtensionContext , languages , env } from 'vscode' ;
14+ import * as vscode from 'vscode' ;
1315
1416import * as nls from 'vscode-nls' ;
17+ nls . config ( { locale : vscode . env . language } ) ;
18+ let localize = nls . loadMessageBundle ( ) ;
19+
20+ const MigratedKey = 'php.validate.executablePaht.migrated' ;
21+ const PathKey = 'php.validate.executablePath' ;
22+
23+ namespace is {
24+ const toString = Object . prototype . toString ;
25+
26+ export function string ( value : any ) : value is string {
27+ return toString . call ( value ) === '[object String]' ;
28+ }
29+ }
30+
31+ let statusBarItem : vscode . StatusBarItem ;
32+
33+ export function activate ( context : vscode . ExtensionContext ) : any {
34+
35+ let workspaceExecutablePath = context . workspaceState . get < string > ( PathKey , undefined ) ;
36+ let migrated = context . workspaceState . get < boolean > ( MigratedKey , false ) ;
37+ let validator = new PHPValidationProvider ( workspaceExecutablePath ) ;
38+ context . subscriptions . push ( vscode . commands . registerCommand ( '_php.onPathClicked' , ( ) => {
39+ onPathClicked ( context , validator ) ;
40+ } ) ) ;
1541
16- export function activate ( context : ExtensionContext ) : any {
17- nls . config ( { locale : env . language } ) ;
42+ statusBarItem = vscode . window . createStatusBarItem ( vscode . StatusBarAlignment . Right , Number . MIN_VALUE ) ;
43+ statusBarItem . text = localize ( 'php.path' , 'Path' ) ;
44+ statusBarItem . color = 'white' ;
45+ statusBarItem . command = '_php.onPathClicked' ;
46+ updateStatusBarItem ( context ) ;
47+ vscode . workspace . onDidChangeConfiguration ( ( ) => updateStatusBarItem ( context ) ) ;
48+ statusBarItem . show ( ) ;
49+
50+ if ( workspaceExecutablePath === void 0 && ! migrated ) {
51+ let settingsExecutablePath = readLocalExecutableSetting ( ) ;
52+ if ( settingsExecutablePath ) {
53+ migrateExecutablePath ( settingsExecutablePath ) . then ( ( value ) => {
54+ // User has pressed escape;
55+ if ( ! value ) {
56+ // activate the validator with the current settings.
57+ validator . activate ( context . subscriptions ) ;
58+ return ;
59+ }
60+ context . workspaceState . update ( MigratedKey , true ) ;
61+ context . workspaceState . update ( PathKey , value ) ;
62+ validator . updateWorkspaceExecutablePath ( value , false ) ;
63+ validator . activate ( context . subscriptions ) ;
64+ updateStatusBarItem ( context ) ;
65+ } ) ;
66+ } else {
67+ validator . activate ( context . subscriptions ) ;
68+ }
69+ } else {
70+ validator . activate ( context . subscriptions ) ;
71+ }
1872
1973 // add providers
20- context . subscriptions . push ( languages . registerCompletionItemProvider ( 'php' , new PHPCompletionItemProvider ( ) , '.' , '$' ) ) ;
21- context . subscriptions . push ( languages . registerHoverProvider ( 'php' , new PHPHoverProvider ( ) ) ) ;
22- context . subscriptions . push ( languages . registerSignatureHelpProvider ( 'php' , new PHPSignatureHelpProvider ( ) , '(' , ',' ) ) ;
74+ context . subscriptions . push ( vscode . languages . registerCompletionItemProvider ( 'php' , new PHPCompletionItemProvider ( ) , '.' , '$' ) ) ;
75+ context . subscriptions . push ( vscode . languages . registerHoverProvider ( 'php' , new PHPHoverProvider ( ) ) ) ;
76+ context . subscriptions . push ( vscode . languages . registerSignatureHelpProvider ( 'php' , new PHPSignatureHelpProvider ( ) , '(' , ',' ) ) ;
2377
24- let validator = new PHPValidationProvider ( ) ;
25- validator . activate ( context . subscriptions ) ;
2678
2779 // need to set in the extension host as well as the completion provider uses it.
28- languages . setLanguageConfiguration ( 'php' , {
80+ vscode . languages . setLanguageConfiguration ( 'php' , {
2981 wordPattern : / ( - ? \d * \. \d \w * ) | ( [ ^ \- \` \~ \! \@ \# \% \^ \& \* \( \) \= \+ \[ \{ \] \} \\ \| \; \: \' \" \, \. \< \> \/ \? \s ] + ) / g
3082 } ) ;
83+ }
84+
85+ function updateStatusBarItem ( context : vscode . ExtensionContext ) : void {
86+ statusBarItem . tooltip = context . workspaceState . get < string > ( PathKey , undefined ) || vscode . workspace . getConfiguration ( 'php.validate' ) . get ( 'executablePath' , undefined ) ;
87+ }
88+
89+ function onPathClicked ( context : vscode . ExtensionContext , validator : PHPValidationProvider ) {
90+ let value = context . workspaceState . get < string > ( PathKey ) ;
91+ vscode . window . showInputBox ( { prompt : localize ( 'php.enterPath' , 'The path to the PHP executable' ) , value : value || '' } ) . then ( value => {
92+ if ( ! value ) {
93+ // User pressed Escape
94+ return ;
95+ }
96+ context . workspaceState . update ( PathKey , value ) ;
97+ validator . updateWorkspaceExecutablePath ( value , true ) ;
98+ updateStatusBarItem ( context ) ;
99+ } , ( error ) => {
100+ } ) ;
101+ }
102+
103+ function migrateExecutablePath ( settingsExecutablePath : string ) : Thenable < string > {
104+ return vscode . window . showInputBox (
105+ {
106+ prompt : localize ( 'php.migrateExecutablePath' , 'Use the above path as the PHP executable path?' ) ,
107+ value : settingsExecutablePath
108+ }
109+ ) ;
110+ }
111+
112+ function readLocalExecutableSetting ( ) : string {
113+ function stripComments ( content : string ) : string {
114+ /**
115+ * First capturing group matches double quoted string
116+ * Second matches single quotes string
117+ * Third matches block comments
118+ * Fourth matches line comments
119+ */
120+ var regexp : RegExp = / ( " (?: [ ^ \\ \" ] * (?: \\ .) ? ) * " ) | ( ' (?: [ ^ \\ \' ] * (?: \\ .) ? ) * ' ) | ( \/ \* (?: \r ? \n | .) * ?\* \/ ) | ( \/ { 2 , } .* ?(?: (?: \r ? \n ) | $ ) ) / g;
121+ let result = content . replace ( regexp , ( match , m1 , m2 , m3 , m4 ) => {
122+ // Only one of m1, m2, m3, m4 matches
123+ if ( m3 ) {
124+ // A block comment. Replace with nothing
125+ return '' ;
126+ } else if ( m4 ) {
127+ // A line comment. If it ends in \r?\n then keep it.
128+ let length = m4 . length ;
129+ if ( length > 2 && m4 [ length - 1 ] === '\n' ) {
130+ return m4 [ length - 2 ] === '\r' ? '\r\n' : '\n' ;
131+ } else {
132+ return '' ;
133+ }
134+ } else {
135+ // We match a string
136+ return match ;
137+ }
138+ } ) ;
139+ return result ;
140+ } ;
141+
142+ try {
143+ let rootPath = vscode . workspace . rootPath ;
144+ if ( ! rootPath ) {
145+ return undefined ;
146+ }
147+ let settingsFile = path . join ( rootPath , '.vscode' , 'settings.json' ) ;
148+ if ( ! fs . existsSync ( settingsFile ) ) {
149+ return undefined ;
150+ }
151+ let content = fs . readFileSync ( settingsFile , 'utf8' ) ;
152+ if ( ! content || content . length === 0 ) {
153+ return undefined ;
154+ }
155+ content = stripComments ( content ) ;
156+ let json = JSON . parse ( content ) ;
157+ let value = json [ 'php.validate.executablePath' ] ;
158+ return is . string ( value ) ? value : undefined ;
159+ } catch ( error ) {
160+ }
161+ return undefined ;
31162}
0 commit comments